From e8c0f20e8858fa70500359c561197962d457db11 Mon Sep 17 00:00:00 2001 From: bmsleight Date: Sun, 20 Jan 2019 13:34:42 +0000 Subject: [PATCH 001/101] Adding lxc install script and apache2 config for lxc --- scripts/lxc/lxc-install.sh | 46 ++++++++++++++++++++++++++++++++++++++ scripts/lxc/paperless.conf | 18 +++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 scripts/lxc/lxc-install.sh create mode 100644 scripts/lxc/paperless.conf diff --git a/scripts/lxc/lxc-install.sh b/scripts/lxc/lxc-install.sh new file mode 100644 index 000000000..0b11db1bc --- /dev/null +++ b/scripts/lxc/lxc-install.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Bash script to instal paperless in lxc containter + +# Get apt up to date +apt-get update + +# Needed for plain Paperless +apt-get -y install unpaper gnupg libpoppler-cpp-dev python3-pyocr tesseract-ocr imagemagick optipng + +# Needed for Apache +apt-get -y install apache2 libapache2-mod-wsgi-py3 +# paperless user +adduser --disabled-password --gecos "" paperless + +#Get Paperless from git (NB: currently fork) +su -c "cd /home/paperless ; git clone https://github.com/bmsleight/paperless" paperless + +# Install Pip Requirements +apt-get -y install python3-pip python3-venv +cd /home/paperless/paperless +pip3 install -r requirements.txt + +#Set up consume directory +su -c "mkdir /home/paperless/consume" paperless + +# Take paperless.conf.example and set consumuption dir +sed -e '/PAPERLESS_CONSUMPTION_DIR=/s/=.*/=\"\/home\/paperless\/consume\/\"/' \ + /home/paperless/paperless/paperless.conf.example >/etc/paperless.conf + +# Update /etc/paperless.conf with PAPERLESS_SECRET_KEY +SECRET=$(strings /dev/urandom | grep -o '[[:alnum:]]' | head -n 30 | tr -d '\n'; echo) +sed -i "s/#PAPERLESS_SECRET_KEY.*/PAPERLESS_SECRET_KEY=$SECRET/g" /etc/paperless.conf + +#Initialise the SQLite database +su -c "cd /home/paperless/paperless/src/ ; ./manage.py migrate" paperless +#Create a user for your Paperless instance +su -c "cd /home/paperless/paperless/src/ ; ./manage.py createsuperuser" paperless +# 167 static files copied to '/home/paperless/paperless/static'. +su -c "cd /home/paperless/paperless/src/ ; ./manage.py collectstatic" paperless + +# Set-up apache +cp /home/paperless/paperless/scripts/lxc/paperless.conf /etc/apache2/sites-available/ +a2dissite 000-default.conf +a2ensite paperless.conf +systemctl reload apache2 diff --git a/scripts/lxc/paperless.conf b/scripts/lxc/paperless.conf new file mode 100644 index 000000000..78fcf867d --- /dev/null +++ b/scripts/lxc/paperless.conf @@ -0,0 +1,18 @@ + + ServerName paperless.lan + + Alias /static/ /home/paperless/paperless/static/ + + Require all granted + + + WSGIScriptAlias / /home/paperless/paperless/src/paperless/wsgi.py + WSGIDaemonProcess example.com user=paperless group=paperless threads=5 python-path=/home/paperless/paperless/src + WSGIProcessGroup paperless.lan + + + + Require all granted + + + From ed2ea1e017155ef3a39964771ae3449adad4d25b Mon Sep 17 00:00:00 2001 From: bmsleight Date: Sun, 20 Jan 2019 13:54:19 +0000 Subject: [PATCH 002/101] Typo in paperless.conf --- scripts/lxc/paperless.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/lxc/paperless.conf b/scripts/lxc/paperless.conf index 78fcf867d..7a6978a65 100644 --- a/scripts/lxc/paperless.conf +++ b/scripts/lxc/paperless.conf @@ -7,7 +7,7 @@ WSGIScriptAlias / /home/paperless/paperless/src/paperless/wsgi.py - WSGIDaemonProcess example.com user=paperless group=paperless threads=5 python-path=/home/paperless/paperless/src + WSGIDaemonProcess paperless.lan user=paperless group=paperless threads=5 python-path=/home/paperless/paperless/src WSGIProcessGroup paperless.lan From 40a026c3518eb291cc4008e0ac1f3c5fedf5c2cf Mon Sep 17 00:00:00 2001 From: bmsleight Date: Sun, 20 Jan 2019 17:38:35 +0000 Subject: [PATCH 003/101] Set-up ftp for consume --- scripts/lxc/lxc-install.sh | 39 +++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/scripts/lxc/lxc-install.sh b/scripts/lxc/lxc-install.sh index 0b11db1bc..3485d0b56 100644 --- a/scripts/lxc/lxc-install.sh +++ b/scripts/lxc/lxc-install.sh @@ -1,6 +1,15 @@ #!/usr/bin/env bash -# Bash script to instal paperless in lxc containter +# Bash script to install paperless in lxc containter + +# Add paperless user with no password +adduser --disabled-password --gecos "" paperless +# Add ftpupload +adduser --disabled-password --gecos "" ftpupload +echo "Set ftpupload password: " +passwd ftpupload +# Allow paperless group to access +adduser paperless ftpupload # Get apt up to date apt-get update @@ -10,8 +19,17 @@ apt-get -y install unpaper gnupg libpoppler-cpp-dev python3-pyocr tesseract-ocr # Needed for Apache apt-get -y install apache2 libapache2-mod-wsgi-py3 -# paperless user -adduser --disabled-password --gecos "" paperless + +# Instll ftp server and make sure all files are owned by paperless +apt-get install proftpd +cat <> /etc/proftpd/proftpd.conf + + UserOwner paperless + GroupOwner paperless + +EOF +systemctl restart proftpd + #Get Paperless from git (NB: currently fork) su -c "cd /home/paperless ; git clone https://github.com/bmsleight/paperless" paperless @@ -24,8 +42,8 @@ pip3 install -r requirements.txt #Set up consume directory su -c "mkdir /home/paperless/consume" paperless -# Take paperless.conf.example and set consumuption dir -sed -e '/PAPERLESS_CONSUMPTION_DIR=/s/=.*/=\"\/home\/paperless\/consume\/\"/' \ +# Take paperless.conf.example and set consumuption dir (ftp dir) +sed -e '/PAPERLESS_CONSUMPTION_DIR=/s/=.*/=\"\/home\/ftpupload\/\"/' \ /home/paperless/paperless/paperless.conf.example >/etc/paperless.conf # Update /etc/paperless.conf with PAPERLESS_SECRET_KEY @@ -44,3 +62,14 @@ cp /home/paperless/paperless/scripts/lxc/paperless.conf /etc/apache2/sites-avail a2dissite 000-default.conf a2ensite paperless.conf systemctl reload apache2 + +sed -e "s/home\/paperless\/project\/virtualenv\/bin\/python/usr\/bin\/python3/" \ + /home/paperless/paperless/scripts/paperless-consumer.service \ + >/etc/systemd/system/paperless-consumer.service + +sed -i "s/\/home\/paperless\/project\/src\/manage.py/\/home\/paperless\/paperless\/src\/manage.py/" \ + /etc/systemd/system/paperless-consumer.service + + +systemctl enable paperless-consumer +systemctl start paperless-consumer From af2eae81eb21ec562d569ddb04911bd907700f86 Mon Sep 17 00:00:00 2001 From: bmsleight Date: Sun, 20 Jan 2019 18:55:39 +0000 Subject: [PATCH 004/101] Consumer tweaks --- scripts/lxc/lxc-install.sh | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/scripts/lxc/lxc-install.sh b/scripts/lxc/lxc-install.sh index 3485d0b56..b6e37b18a 100644 --- a/scripts/lxc/lxc-install.sh +++ b/scripts/lxc/lxc-install.sh @@ -1,6 +1,14 @@ #!/usr/bin/env bash # Bash script to install paperless in lxc containter +# paperless.lan +# +# Will set-up paperless, apache2 and proftpd +# +# lxc launch ubuntu: paperless +# lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/danielquinn/paperless/master/scripts/lxc/lxc-install.sh && /bin/bash lxc-install.sh" +# +# # Add paperless user with no password adduser --disabled-password --gecos "" paperless @@ -10,6 +18,7 @@ echo "Set ftpupload password: " passwd ftpupload # Allow paperless group to access adduser paperless ftpupload +chmod g+w /home/ftpupload # Get apt up to date apt-get update @@ -20,8 +29,8 @@ apt-get -y install unpaper gnupg libpoppler-cpp-dev python3-pyocr tesseract-ocr # Needed for Apache apt-get -y install apache2 libapache2-mod-wsgi-py3 -# Instll ftp server and make sure all files are owned by paperless -apt-get install proftpd +# Install ftp server and make sure all uplaoded files are owned by paperless +apt-get -y install proftpd cat <> /etc/proftpd/proftpd.conf UserOwner paperless @@ -39,9 +48,6 @@ apt-get -y install python3-pip python3-venv cd /home/paperless/paperless pip3 install -r requirements.txt -#Set up consume directory -su -c "mkdir /home/paperless/consume" paperless - # Take paperless.conf.example and set consumuption dir (ftp dir) sed -e '/PAPERLESS_CONSUMPTION_DIR=/s/=.*/=\"\/home\/ftpupload\/\"/' \ /home/paperless/paperless/paperless.conf.example >/etc/paperless.conf @@ -73,3 +79,8 @@ sed -i "s/\/home\/paperless\/project\/src\/manage.py/\/home\/paperless\/paperle systemctl enable paperless-consumer systemctl start paperless-consumer + +# convert-im6.q16: not authorized +# Security risk ? +# https://stackoverflow.com/questions/42928765/convertnot-authorized-aaaa-error-constitute-c-readimage-453 +mv /etc/ImageMagick-6/policy.xml /etc/ImageMagick-6/policy.xmlout From f74313f3abb01169ee5ed85dfd422de3dd9c732a Mon Sep 17 00:00:00 2001 From: bmsleight Date: Sun, 20 Jan 2019 21:19:43 +0000 Subject: [PATCH 005/101] Adding lxc documentation --- docs/_static/Screenshot_first_logged.png | Bin 0 -> 61336 bytes docs/_static/Screenshot_first_run_login.png | Bin 0 -> 26481 bytes .../_static/Screenshot_upload_and_scanned.png | Bin 0 -> 115989 bytes docs/_static/lxc-install.svg | 44 ++++++++++++++++++ docs/index.rst | 1 + docs/scanners.rst | 4 ++ docs/screenshots.rst | 16 +++++++ docs/setup.rst | 37 ++++++++++++++- 8 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 docs/_static/Screenshot_first_logged.png create mode 100644 docs/_static/Screenshot_first_run_login.png create mode 100644 docs/_static/Screenshot_upload_and_scanned.png create mode 100644 docs/_static/lxc-install.svg create mode 100644 docs/screenshots.rst diff --git a/docs/_static/Screenshot_first_logged.png b/docs/_static/Screenshot_first_logged.png new file mode 100644 index 0000000000000000000000000000000000000000..9b9c6072be11894c3ef2e969c16e54bf73f01b13 GIT binary patch literal 61336 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

9VD{Nc|#42Hdb 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 literal 0 HcmV?d00001 diff --git a/docs/_static/Screenshot_first_run_login.png b/docs/_static/Screenshot_first_run_login.png new file mode 100644 index 0000000000000000000000000000000000000000..d704f168229a220297e5fd97f206e0ce85596f54 GIT binary patch literal 26481 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 Uynin^A%V`HG5@L5=<4l%0t4u?MF0Q* literal 0 HcmV?d00001 diff --git a/docs/_static/Screenshot_upload_and_scanned.png b/docs/_static/Screenshot_upload_and_scanned.png new file mode 100644 index 0000000000000000000000000000000000000000..7b433b2ca6f2a164f0c7b7bc91d5fe0434791eda GIT binary patch literal 115989 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%0AZx-W6Sl7T_FLXbEaItb-Wbpa) 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 literal 0 HcmV?d00001 diff --git a/docs/_static/lxc-install.svg b/docs/_static/lxc-install.svg new file mode 100644 index 000000000..7ffe1bbdf --- /dev/null +++ b/docs/_static/lxc-install.svg @@ -0,0 +1,44 @@ + + + + + + + + + + Need to get 1818 kB of archives.Collecting ipython-genutils==0.2.0 (from -r requirements.txt (line 32))24% [Waiting for headers] Setting up libfile-fcntllock-perl (0.22-3build2) ...Collecting sphinxcontrib-websupport==1.1.0 (from -r requirements.txt (line 71))Get:45 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxcb-shm0 amd64 1.13-1 [5572 B] 19% |██████▎ | 614kB 5.2MB/s eta 0:00:01 99% |████████████████████████████████| 3.1MB 6.0MB/s eta 0:00:01 bms@pingu:~$ ex -extensions-2.1.3 django-filter-2.0.0 djangorestframework-3.9.0 docopt-0.6.2 docutils-0.14 execnet-1.5.0 factory-boy-2.11.1 faker-0.Unpacking liblqr-1-0:amd64 (0.4.2-2.1) ...Selecting previously unselected package python3-xdg. 52% |████████████████▉ | 266kB 6.0MB/s eta 0:00:01 62% |████████████████████ | 5.1MB 5.8MB/s eta 0:00:01 100% |████████████████████████████████| 215kB 2.6MB/s 50% [Waiting for headers] 3755 kB/s 8s Downloading https://files.pythonhosted.org/packages/1b/92/a45a140b4024988f65eb76020101fa6da968b43716121595452b8bafb506/pytest_xdis binutils binutils-common binutils-x86-64-linux-gnu build-essential cpp cpp-7 dh-python dpkg-dev fakeroot g++ g++-7 gcc gcc-7 Not uninstalling urllib3 at /usr/lib/python3/dist-packages, outside environment /usr python-crypto-doc gnome-keyring libkf5wallet-bin gir1.2-gnomekeyring-1.0 python-secretstorage-doc python-setuptools-docGet:104 http://archive.ubuntu.com/ubuntu bionic/universe amd64 liblept5 amd64 1.75.3-3 [929 kB] 76% |████████████████████████▌ | 1.5MB 6.0MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/fi.js'bms@pingu:~$ # Lanuch the new machineSelecting previously unselected package libpoppler-cpp0v5:amd64.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/he.js'Setting up tesseract-ocr (4.00~git2288-10f4998a-2) ...Adding system user `ftp' (UID 112) ... Downloading https://files.pythonhosted.org/packages/dd/9d/fb75af584b850a902c9ce5ec96ea5c623978113b8a240ab414e1a435df93/pytest_fork 62% |███████████████████▉ | 522kB 5.9MB/s eta 0:00:01 Get:15 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 imagemagick-6-common all 8:6.9.7.4+dfsg-16ubuntu6.4 [60.9 kB]Get:19 http://archive.ubuntu.com/ubuntu bionic/main amd64 poppler-data all 0.4.8-2 [1479 kB]Selecting previously unselected package python-pip-whl.Preparing to unpack .../048-libgsm1_1.0.13-4build1_amd64.deb ...59% [43 libpython3.6-dev 12.1 MB/44.8 MB 27%] 4081 kB/s 9sGet:10 http://archive.ubuntu.com/ubuntu bionic/main amd64 libmpc3 amd64 1.1.0-1 [40.8 kB]49% [10 Sources store 0 B] [18 Packages 2685 B/8570 kB 0%] python3-pip python3-secretstorage python3-setuptools python3-venv python3-wheel python3-xdg python3.6-dev python3.6-venvCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/vi.js'Reading package lists... 88%Receiving objects: 14% (780/5570) Setting up libpoppler-cpp-dev:amd64 (0.62.0-2ubuntu2.5) ... 79% |█████████████████████████▍ | 5.6MB 6.1MB/s eta 0:00:01 Setting up gcc-7-base:amd64 (7.3.0-27ubuntu1~18.04) ...90% [18 Packages store 0 B] [21 Translation-en 2687 B/108 kB 2%] libcups2 libcupsfilters1 libcupsimage2 libdatrie1 libdjvulibre-text libdjvulibre21 libdrm-amdgpu1 libdrm-intel1 libdrm-nouveau2 40% |████████████▉ | 2.9MB 5.9MB/s eta 0:00:01 Extracting templates from packages: 85% Stored in directory: /root/.cache/pip/wheels/7c/06/54/bc84598ba1daf8f970247f550b175aaaee85f68b4b0c5ab2c641% [Waiting for headers] 3755 kB/s 10s Applying sessions.0001_initial... OKSelecting previously unselected package libxrender1:amd64.Selecting previously unselected package vdpau-driver-all:amd64.Get:3 http://archive.ubuntu.com/ubuntu bionic/main amd64 libfontconfig1 amd64 2.12.6-0ubuntu2 [137 kB]Get:83 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libavcodec57 amd64 7:3.4.4-0ubuntu0.18.04.1 [4592 kB] Unpacking libfontconfig1:amd64 (2.12.6-0ubuntu2) ...Unpacking libxcb-shm0:amd64 (1.13-1) ...23% [11 Packages store 0 B] [10 Sources 1142 kB/9051 kB 13%] [Waiting for headers] 91% |█████████████████████████████▎ | 7.4MB 5.9MB/s eta 0:00:01 Preparing to unpack .../095-libdrm-amdgpu1_2.4.91-2_amd64.deb ... 52% |████████████████▉ | 112kB 6.5MB/s eta 0:00:01 Setting up python3-crypto (2.6.1-8ubuntu2) ...Adding new group `paperless' (1000) ...50% [43 libpython3.6-dev 2540 kB/44.8 MB 6%] 4081 kB/s 11sSelecting previously unselected package libjpeg8:amd64. 76% |████████████████████████▍ | 5.4MB 6.0MB/s eta 0:00:01 binutils-doc cpp-doc gcc-7-locales debian-keyring g++-multilib g++-7-multilib gcc-7-doc libstdc++6-7-dbg gcc-multilib autoconf 61% |███████████████████▊ | 614kB 5.9MB/s eta 0:00:01 Stored in directory: /root/.cache/pip/wheels/15/ae/df/a67bf1ed84e9bf230187d36d8dcfd30072bea0236cb059ed91passwd: password updated successfullyGet:26 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [489 kB] 81% |██████████████████████████▏ | 92kB 5.8MB/s eta 0:00:01 pygments, traitlets, wcwidth, prompt-toolkit, ipython, langdetect, more-itertools, pyparsing, packaging, pdftotext, pillow, pluggy, Unpacking libltdl7:amd64 (2.4.6-2) ...Selecting previously unselected package libdpkg-perl. 10% |███▍ | 204kB 6.0MB/s eta 0:00:01 Selecting previously unselected package libpoppler73:amd64.Get:6 http://security.ubuntu.com/ubuntu bionic-security/main Sources [70.2 kB] Applying documents.0017_auto_20170512_0507... OKPreparing to unpack .../16-liblsan0_8.2.0-1ubuntu2~18.04_amd64.deb ...Enabling module access_compat.Get:38 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libva-drm2 amd64 2.1.0-3 [6880 B]Password: Downloading https://files.pythonhosted.org/packages/21/35/60094dbadd9de2035873390b1cac25e01da605844eba6a07a53a82fa4adc/pdftotext-276% [Waiting for headers] 3755 kB/s 4sCollecting faker==0.9.2 (from -r requirements.txt (line 24))Unpacking libsoxr0:amd64 (0.1.2-3) ...Preparing to unpack .../020-libavahi-common-data_0.7-3.1ubuntu1.1_amd64.deb ...33% [50 libmp3lame0 4061 B/136 kB 3%] Setting up i965-va-driver:amd64 (2.1.0-0ubuntu1) ...Get:34 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 python3-distutils all 3.6.7-1~18.04 [141 kB] Setting up libdatrie1:amd64 (0.2.10-7) ...Get:11 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 liblcms2-2 amd64 2.9-1ubuntu0.1 [139 kB] 83% |██████████████████████████▉ | 6.8MB 6.0MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/it.js'Preparing to unpack .../09-libapache2-mod-wsgi-py3_4.5.17-1_amd64.deb ... 52% |████████████████▊ | 522kB 5.9MB/s eta 0:00:01 Selecting previously unselected package fontconfig.Get:17 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 liblsan0 amd64 8.2.0-1ubuntu2~18.04 [132 kB]Collecting urllib3==1.24.1 (from -r requirements.txt (line 78)) Downloading https://files.pythonhosted.org/packages/3a/9a/9d878f8d885706e2530402de6417141129a943802c084238914fa6798d97/atomicwriteSelecting previously unselected package libexpat1-dev:amd64.bms@FortBoyard:~$ exi Setting up libgs9-common (9.26~dfsg+0-0ubuntu0.18.04.3) ... 45% |██████████████▍ | 890kB 5.9MB/s eta 0:00:01 bms@pingu:~$ e Collecting tox==3.5.3 (from -r requirements.txt (line 75))Preparing to unpack .../19-libcilkrts5_7.3.0-27ubuntu1~18.04_amd64.deb ...Setting up libatomic1:amd64 (8.2.0-1ubuntu2~18.04) ... 20% |██████▋ | 1.7MB 5.6MB/s eta 0:00:02 Preparing to unpack .../016-libmagickwand-6.q16-3_8%3a6.9.7.4+dfsg-16ubuntu6.4_amd64.deb ...10% [Waiting for headers] 99% |████████████████████████████████| 839kB 6.6MB/s eta 0:00:01 Selecting previously unselected package libcilkrts5:amd64.Unpacking libcups2:amd64 (2.2.7-1ubuntu2.3) ... fonts-noto ghostscript-x i965-va-driver-shaders imagemagick-doc autotrace cups-bsd | lpr | lprng enscript ffmpeg gimp gnuplot 18% |██████ | 501kB 5.8MB/s eta 0:00:01 Get:21 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libavahi-common-data amd64 0.7-3.1ubuntu1.1 [22.1 kB] 52% |████████████████▊ | 4.2MB 5.9MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/dashboard.css'Setting up libnspr4:amd64 (2:4.18-1ubuntu1) ... Running setup.py bdist_wheel for pdftotext ... \39% [74 libvpx5 2613 B/798 kB 0%] 3755 kB/s 11sPreparing to unpack .../32-python3-lib2to3_3.6.7-1~18.04_all.deb ...52% [43 libpython3.6-dev 4765 kB/44.8 MB 11%] 4081 kB/s 11sSelecting previously unselected package libxfixes3:amd64.48% [10 Sources 8678 kB/9051 kB 96%] Unpacking libmagickcore-6.q16-3-extra:amd64 (8:6.9.7.4+dfsg-16ubuntu6.4) ...34% [Waiting for headers] Enabling module mime.Creating home directory `/home/paperless' ... 41% |█████████████▏ | 1.1MB 5.9MB/s eta 0:00:01 Preparing to unpack .../079-libxvidcore4_2%3a1.3.5-1_amd64.deb ...Setting up libavahi-common-data:amd64 (0.7-3.1ubuntu1.1) ...bms@FortBoyard:~$ # ssh to my machine running Linux Containers Applying documents.0006_auto_20160123_0430... OKUnpacking libaacs0:amd64 (0.9.0-1) ... Stored in directory: /root/.cache/pip/wheels/98/b0/dd/29e28ff615af3dda4c67cab719dd51357597eabff926976b45 64% |████████████████████▋ | 593kB 5.8MB/s eta 0:00:01 Selecting previously unselected package libdjvulibre-text.Preparing to unpack .../130-optipng_0.7.6-1.1_amd64.deb ...Get:107 http://archive.ubuntu.com/ubuntu bionic/main amd64 libwmf0.2-7 amd64 0.2.8.4-12 [150 kB] 100% |████████████████████████████████| 61kB 3.9MB/s lxc-install.sh 100%[==========================================================>] 2.98K --.-KB/s in 0s Username (leave blank to use 'paperless'): Unpacking libxcb-xfixes0:amd64 (1.13-1) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/jquery/jquery.js'Unpacking libpango-1.0-0:amd64 (1.40.14-1ubuntu0.1) ...54% [43 libpython3.6-dev 6805 kB/44.8 MB 15%] 4081 kB/s 10sCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/inlines.js'30% [42 libavutil55 2613 B/190 kB 1%] 47% |███████████████ | 3.4MB 5.2MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-calendar.svg'34% [Working] 100% [Working] 4630 kB/s 0s Downloading https://files.pythonhosted.org/packages/cb/89/e3687d3ed99bc882793f82634e9824e62499fdfdc4b1ae39e211c5b05017/tzlocal-1.5Setting up libpoppler-cpp0v5:amd64 (0.62.0-2ubuntu2.5) ...Setting up poppler-data (0.4.8-2) ... 93% |█████████████████████████████▉ | 2.5MB 5.9MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-addlink.svg'Preparing to unpack .../013-libtiff5_4.0.9-5_amd64.deb ... 65% |█████████████████████ | 2.0MB 6.0MB/s eta 0:00:01 20% |██████▌ | 399kB 5.9MB/s eta 0:00:01 Preparing to unpack .../25-libstdc++-7-dev_7.3.0-27ubuntu1~18.04_amd64.deb ...Preparing to unpack .../102-libilmbase12_2.2.0-11ubuntu2_amd64.deb ...Collecting docutils==0.14 (from -r requirements.txt (line 21))Preparing to unpack .../02-libaprutil1-dbd-sqlite3_1.6.1-2_amd64.deb ...24% [24 gcc-7 2611 B/7455 kB 0%] Selecting previously unselected package libgcc-7-dev:amd64.2.tar.gz(Reading database ... 32755 files and directories currently installed.) Applying documents.0021_document_storage_type... OK Running setup.py bdist_wheel for python-levenshtein ... doneSelecting previously unselected package libalgorithm-merge-perl.Get:81 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libzvbi-common all 0.2.35-13 [32.1 kB] 48% [Waiting for headers] 4081 kB/s 12s63% [43 libpython3.6-dev 16.8 MB/44.8 MB 37%] 4081 kB/s 8sGet:18 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libtsan0 amd64 8.2.0-1ubuntu2~18.04 [288 kB]24% [Waiting for headers] Get:113 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpoppler73 amd64 0.62.0-2ubuntu2.5 [800 kB] '/usr/share/proftpd/templates/welcome.msg' -> '/srv/ftp/welcome.msg.proftpd-new'Selecting previously unselected package libva-x11-2:amd64.Unpacking libva-drm2:amd64 (2.1.0-3) ...nv-0.9.1-py2.py3-none-any.whl netpbm poppler-data python3-olefile python3-pil tesseract-ocr-eng tesseract-ocr-osd va-driver-all vdpau-driver-allSelecting previously unselected package apache2-data.Preparing to unpack .../035-libaacs0_0.9.0-1_amd64.deb ...update-alternatives: using /usr/bin/identify-im6.q16 to provide /usr/bin/identify-im6 (identify-im6) in auto modee 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/ 30% |█████████▉ | 604kB 6.0MB/s eta 0:00:01 Collecting pytest-cov==2.6.0 (from -r requirements.txt (line 54)) 66% |█████████████████████▍ | 5.4MB 906kB/s eta 0:00:03 Building dependency tree... 0%Unpacking libtesseract4 (4.00~git2288-10f4998a-2) ...Ignoring python-levenshtein: markers 'extra == "speedup"' don't match your environment58% [Waiting for headers] 3755 kB/s 7s 97% |███████████████████████████████▏| 6.9MB 37.4MB/s eta 0:00:01 Get:56 http://archive.ubuntu.com/ubuntu bionic/main amd64 libthai-data all 0.1.27-2 [133 kB]Setting up python3-lib2to3 (3.6.7-1~18.04) ... 86% |███████████████████████████▋ | 194kB 5.9MB/s eta 0:00:01 40% |█████████████ | 92kB 5.8MB/s eta 0:00:01 Collecting requests==2.20.0 (from -r requirements.txt (line 67))Collecting djangorestframework==3.9.0 (from -r requirements.txt (line 19))Setting up librsvg2-2:amd64 (2.40.20-2) ...Get:22 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libavahi-common3 amd64 0.7-3.1ubuntu1.1 [21.7 kB] Downloading https://files.pythonhosted.org/packages/d1/e6/adb3be5576f5d27c6faa33f1e9fea8fe5dbd9351db12148de948507e352c/prompt_tooly2.py3-none-any.whl (53kB)Setting up libaprutil1-dbd-sqlite3:amd64 (1.6.1-2) ...Preparing to unpack .../17-libtsan0_8.2.0-1ubuntu2~18.04_amd64.deb ... Not uninstalling pyocr at /usr/lib/python3/dist-packages, outside environment /usr21% [30 libgs9 2611 B/2263 kB 0%] 11% |███▊ | 942kB 3.6MB/s eta 0:00:02 25% [10 Sources 1584 kB/9051 kB 17%] [12 Translation-en 2688 B/91.6 kB 3%] 32% |██████████▌ | 2.7MB 5.9MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/hi.js' 11% |███▋ | 112kB 6.5MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/sorting-icons.svg'Preparing to unpack .../076-libwebpmux3_0.6.1-2_amd64.deb ...Unpacking libxcb-render0:amd64 (1.13-1) ... 48% |███████████████▌ | 3.9MB 6.0MB/s eta 0:00:01 86% |███████████████████████████▋ | 727kB 6.0MB/s eta 0:00:01 Selecting previously unselected package libgsm1:amd64.38% [Waiting for headers] 3755 kB/s 11s Applying auth.0001_initial... OKPreparing to unpack .../129-netpbm_2%3a10.0-15.3build1_amd64.deb ...Selecting previously unselected package dpkg-dev.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ko.js'Unpacking libnss3:amd64 (2:3.35-2ubuntu2.1) ...55% [Waiting for headers] 3755 kB/s 8s Downloading https://files.pythonhosted.org/packages/d0/43/2160a300e0b77a929a980f36ac7427dcef8f4ddac7a8c21e5a8baedad828/tox-3.5.3-pPreparing to unpack .../31-build-essential_12.4ubuntu1_amd64.deb ...Preparing to unpack .../57-python3-xdg_0.25-4ubuntu1_all.deb ...56% [Working] 3755 kB/s 8sPreparing to unpack .../36-fakeroot_1.22-2ubuntu1_amd64.deb ...20.0-py2.py3-none-any.whl (60kB)Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/sk.js'Receiving objects: 93% (5181/5570), 4.67 MiB | 3.10 MiB/s 19% [18 libtsan0 2613 B/288 kB 1%] Preparing to unpack .../091-libbdplus0_0.1.2-2_amd64.deb ...28% [24 gcc-7 4531 kB/7455 kB 61%] 16% |█████▏ | 1.3MB 4.3MB/s eta 0:00:02 Setting up libpoppler73:amd64 (0.62.0-2ubuntu2.5) ...Setting up make (4.1-9.1ubuntu1) ... 98% |███████████████████████████████▌| 634kB 5.8MB/s eta 0:00:01 Unpacking libmpx2:amd64 (8.2.0-1ubuntu2~18.04) ...Setting up libwmf0.2-7:amd64 (0.2.8.4-12) ...Get:29 http://archive.ubuntu.com/ubuntu bionic-updates/universe Translation-en [175 kB]Copying '/home/paperless/paperless/src/documents/static/documents/img/tiff.png'Requirement already satisfied: jinja2==2.10 in /usr/lib/python3/dist-packages (from -r requirements.txt (line 35)) Downloading https://files.pythonhosted.org/packages/84/71/c8ca4f5bb1e08401b916c68003acf0a0655df935d74d93bf3f3364b310e0/backcall-0.Get:9 http://archive.ubuntu.com/ubuntu bionic/main amd64 libjbig0 amd64 2.1-3.1build1 [26.7 kB]Preparing to unpack .../003-fontconfig_2.12.6-0ubuntu2_amd64.deb ...Setting up libxcb-present0:amd64 (1.13-1) ... 72% |███████████████████████ | 5.1MB 5.9MB/s eta 0:00:01 Applying auth.0003_alter_user_email_max_length... OKSelecting previously unselected package g++. 68% |█████████████████████▉ | 2.1MB 5.9MB/s eta 0:00:01 Preparing to unpack .../023-libcups2_2.2.7-1ubuntu2.3_amd64.deb ...Unpacking python3-pyocr (0.3.0-1) ...Preparing to unpack .../117-libsensors4_1%3a3.4.0-4_amd64.deb ...Reading package lists... 99%Get:33 http://archive.ubuntu.com/ubuntu bionic/main amd64 hicolor-icon-theme all 0.17-2 [9976 B]Preparing to unpack .../083-libbluray2_1%3a1.0.2-3_amd64.deb ...28% [10 Sources 2262 kB/9051 kB 25%] [Waiting for headers] Unpacking libxcb-present0:amd64 (1.13-1) ...Setting up libjbig0:amd64 (2.1-3.1build1) ... - https://blog.ubuntu.com/2018/12/10/using-gpgpus-with-kubernetesUnpacking tesseract-ocr-eng (4.00~git24-0e00fe6-1.2) ...22% [10 Sources 895 kB/9051 kB 10%] [11 Packages 188 kB/242 kB 78%] Setting up libopus0:amd64 (1.1.2-1ubuntu1) ... Downloading https://files.pythonhosted.org/packages/19/6c/b2ac85b3f0b48ac968af3741c4f020bf272ab9dabbd1643e9c719441099a/factory_boyPreparing to unpack .../126-libxshmfence1_1.3-1_amd64.deb ...info: Executing deferred 'a2enmod wsgi' for package libapache2-mod-wsgi-py312% [3 proftpd-basic 2611 B/2015 kB 0%] Building dependency tree... 50%Selecting previously unselected package python3-crypto.Extracting templates from packages: 42%Enabling module authz_core.Selecting previously unselected package libsensors4:amd64.Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/docs/img/favicon.ico'Unpacking libsnappy1v5:amd64 (1.1.7-1) ... Downloading https://files.pythonhosted.org/packages/3e/6a/a3f909083079d03bde11d06ab23088886bbe25f2c97fbe4bb865e2bf05bc/pytest-sugaPreparing to unpack .../28-make_4.1-9.1ubuntu1_amd64.deb ...Username (leave blank to use 'paperless'): Unpacking libpciaccess0:amd64 (0.14-1) ...Unpacking liblcms2-2:amd64 (2.9-1ubuntu0.1) ... Applying documents.0022_auto_20181007_1420... OKSelecting previously unselected package libxcb-shm0:amd64.Preparing to unpack .../057-libthai0_0.1.27-2_amd64.deb ...Unpacking tesseract-ocr-osd (4.00~git24-0e00fe6-1.2) ...Get:99 http://archive.ubuntu.com/ubuntu bionic/main amd64 libdrm-nouveau2 amd64 2.4.91-2 [16.5 kB] Selecting previously unselected package fonts-droid-fallback.Preparing to unpack .../065-libsnappy1v5_1.1.7-1_amd64.deb ...Unpacking librsvg2-2:amd64 (2.40.20-2) ...Unpacking libgraphite2-3:amd64 (1.3.11-2) ... 48% |███████████████▌ | 1.5MB 6.0MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/login.css'update-alternatives: using /usr/bin/stream-im6.q16 to provide /usr/bin/stream (stream) in auto modePreparing to unpack .../046-libcairo2_1.15.10-2_amd64.deb ...Preparing to unpack .../037-libva-drm2_2.1.0-3_amd64.deb ... manpages-dev python-pip-whl python3-crypto python3-dev python3-distutils python3-keyring python3-keyrings.alt python3-lib2to3Adding user `paperless' to group `ftpupload' ...Collecting ipython==7.1.1 (from -r requirements.txt (line 33))Setting up python3-wheel (0.30.0-0.2) ...Setting up libpaper1:amd64 (1.1.24+nmu5ubuntu1) ...Selecting previously unselected package libcupsimage2:amd64. 87% |████████████████████████████ | 6.2MB 5.8MB/s eta 0:00:01 Setting up libdjvulibre21:amd64 (3.5.27.1-8) ...Setting up libsnappy1v5:amd64 (1.1.7-1) ...Selecting previously unselected package libalgorithm-diff-perl.Get:26 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libstdc++-7-dev amd64 7.3.0-27ubuntu1~18.04 [1463 kB] 3% |█ | 245kB 1.6MB/s eta 0:00:05 Processing triggers for ufw (0.35-5) ...3 kB]Unpacking libxcb-dri3-0:amd64 (1.13-1) ... 56% |██████████████████ | 307kB 6.1MB/s eta 0:00:01 Preparing to unpack .../078-libx265-146_2.6-3_amd64.deb ... 15% |█████ | 409kB 5.2MB/s eta 0:00:01 0% [5 Sources store 0 B] [4 InRelease gpgv 74.6 kB] [10 Sources 14.3 kB/9051 kB 0%] [Waiting for headers] Get:39 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxfixes3 amd64 1:5.0.3-1 [10.8 kB]Unpacking libbdplus0:amd64 (0.1.2-2) ... 89% |████████████████████████████▊ | 2.4MB 6.0MB/s eta 0:00:01 Selecting previously unselected package libavutil55:amd64.Selecting previously unselected package python3.6-dev.Unpacking libcc1-0:amd64 (8.2.0-1ubuntu2~18.04) ...Collecting virtualenv==16.1.0 (from -r requirements.txt (line 79))Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/jquery.init.js'0% [1 fonts-dejavu-core 2612 B/1041 kB 0%] Selecting previously unselected package libjpeg-turbo8:amd64.Collecting tzlocal==1.5.1 (from -r requirements.txt (line 77))Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/fontawesome-webfont.woff'Get:125 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxcb-sync1 amd64 1.13-1 [8808 B] Selecting previously unselected package libcc1-0:amd64.Get:10 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libapache2-mod-wsgi-py3 amd64 4.5.17-1 [87.8 kB].1.tar.gz1.0.7.zip (998kB) 0 upgraded, 11 newly installed, 0 to remove and 19 not upgraded.Selecting previously unselected package libsnappy1v5:amd64.Collecting sphinx==1.8.1 (from -r requirements.txt (line 70))83% [Working] 4630 kB/s 2sPreparing to unpack .../105-libopenexr22_2.2.0-11.1ubuntu1_amd64.deb ... 60% |███████████████████▎ | 389kB 5.8MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/css/bootstrap-theme.min.css'75% [10 Sources store 0 B] Unpacking libgs9:amd64 (9.26~dfsg+0-0ubuntu0.18.04.3) ...Selecting previously unselected package fakeroot. Downloading https://files.pythonhosted.org/packages/89/e6/b5a1de8b0cc4e07ca1b305a4fcc3f9806025c1b651ea302646341222f88b/pexpect-4.6 6% |██▏ | 481kB 5.9MB/s eta 0:00:02 91% [18 Packages store 0 B] Setting up libpaper-utils (1.1.24+nmu5ubuntu1) ... 100% |████████████████████████████████| 92kB 3.7MB/s Downloading https://files.pythonhosted.org/packages/bc/2a/61a8f9719bd6df5b421abd91740cb0595fc3c17b28eaf89fe4f144472ca6/psycopg2-2.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/gl.js'Get:114 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpoppler-cpp0v5 amd64 0.62.0-2ubuntu2.5 [28.0 kB] Stored in directory: /root/.cache/pip/wheels/75/fc/26/357bc139b726977ab08817308ce76d96a26bdbe2329a43b15a27% [13 Packages store 0 B] [10 Sources 2085 kB/9051 kB 23%] [Waiting for headers] Reading package lists... 96% Found existing installation: attrs 17.4.052% [Waiting for headers] 3755 kB/s 8s6% [Working] 2% |▉ | 194kB 6.0MB/s eta 0:00:02 99% |███████████████████████████████▉| 993kB 6.0MB/s eta 0:00:01 Preparing to unpack .../proftpd-basic_1.3.5e-1build1_amd64.deb ...Get:94 http://archive.ubuntu.com/ubuntu bionic/main amd64 libdjvulibre-text all 3.5.27.1-8 [49.1 kB] 86% |███████████████████████████▊ | 1.7MB 5.9MB/s eta 0:00:01 83% |██████████████████████████▋ | 829kB 5.9MB/s eta 0:00:01 0% [2 InRelease gpgv 83.2 kB] Preparing to unpack .../07-gcc-7-base_7.3.0-27ubuntu1~18.04_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/nb.js' 9% |███ | 778kB 3.4MB/s eta 0:00:03 Setting up libtiff5:amd64 (4.0.9-5) ...Selecting previously unselected package hicolor-icon-theme.Preparing to unpack .../019-fonts-noto-mono_20171026-2_all.deb ...Get:95 http://archive.ubuntu.com/ubuntu bionic/main amd64 libdjvulibre21 amd64 3.5.27.1-8 [559 kB] 50% |████████████████▎ | 1.0MB 5.9MB/s eta 0:00:01 Preparing to unpack .../018-poppler-data_0.4.8-2_all.deb ... 93% |██████████████████████████████ | 7.6MB 6.0MB/s eta 0:00:01 Selecting previously unselected package python3-distutils.Unpacking python3-keyring (10.6.0-1) ...47% [Waiting for headers] 4081 kB/s 12sGet:8 http://archive.ubuntu.com/ubuntu bionic/main amd64 libfftw3-double3 amd64 3.3.7-1 [735 kB] 14% |████▋ | 1.2MB 3.9MB/s eta 0:00:02 Setting up python3-secretstorage (2.3.1-2) ...Setting up python3-keyrings.alt (3.0-1) ...Get:131 http://archive.ubuntu.com/ubuntu bionic/main amd64 optipng amd64 0.7.6-1.1 [83.4 kB] 24% |████████ | 2.0MB 5.5MB/s eta 0:00:02 Warning: The home dir /run/proftpd you specified can't be accessed: No such file or directory 40% |█████████████ | 3.3MB 6.0MB/s eta 0:00:01 Resolving deltas: 8% (293/3560) 2% [Waiting for headers] Unpacking optipng (0.7.6-1.1) ...Resolving raw.githubusercontent.com (raw.githubusercontent.com)... Found existing installation: pyocr 0.3.030% [Waiting for headers] Get:141 http://archive.ubuntu.com/ubuntu bionic/main amd64 vdpau-driver-all amd64 1.1.1-3ubuntu1 [4674 B] Selecting previously unselected package libpython3.6-dev:amd64.Get:100 http://archive.ubuntu.com/ubuntu bionic/main amd64 libdrm-radeon1 amd64 2.4.91-2 [21.7 kB] 52% |████████████████▋ | 112kB 6.4MB/s eta 0:00:01 Get:5 http://archive.ubuntu.com/ubuntu bionic/main amd64 libc-dev-bin amd64 2.27-3ubuntu1 [71.8 kB] 98% |███████████████████████████████▌| 61kB 6.3MB/s eta 0:00:01 Running setup.py bdist_wheel for pyocr ... doneGet:24 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 gcc-7 amd64 7.3.0-27ubuntu1~18.04 [7455 kB]Setting up libfftw3-double3:amd64 (3.3.7-1) ...Preparing to unpack .../051-libopus0_1.1.2-1ubuntu1_amd64.deb ...Get:9 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 apache2 amd64 2.4.29-1ubuntu4.5 [95.1 kB]Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/search.svg'28% [Working] 88% |████████████████████████████▍ | 61kB 5.1MB/s eta 0:00:01 0.6.0-py2.py3-none-any.whl31% [Waiting for headers] Setting up libpciaccess0:amd64 (0.14-1) ...56% [Waiting for headers] 3755 kB/s 8sGet:53 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 python3-pip all 9.0.1-2.3~ubuntu1 [114 kB] Preparing to unpack .../06-apache2-utils_2.4.29-1ubuntu4.5_amd64.deb ... Running setup.py bdist_wheel for tzlocal ... done Downloading https://files.pythonhosted.org/packages/36/fa/08e9e6e0e3cbd1d362c3bbee8d01d0aedb2155c4ac112b19ef3cae8eed8d/docutils-0.90% [Waiting for headers] 4611 kB/s 1sCopying '/home/paperless/paperless/src/paperless/static/paperless/img/logo-light.png'Setting up libaacs0:amd64 (0.9.0-1) ... 65% |█████████████████████ | 501kB 5.9MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/select2.full.js'Setting up build-essential (12.4ubuntu1) ...Enabling conf security.Collecting certifi==2018.10.15 (from -r requirements.txt (line 8))Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.svg'Get:35 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 imagemagick amd64 8:6.9.7.4+dfsg-16ubuntu6.4 [14.2 kB]Setting up liblua5.2-0:amd64 (5.2.4-1.1build1) ... Downloading https://files.pythonhosted.org/packages/02/75/d041ed00994fbac4c5183e6f4bf6c906506bef8da7a57ef3fc825f171020/pytest-3.9.41% [29 make 4061 B/154 kB 3%] 4081 kB/s 12sCollecting pytest-env==0.6.2 (from -r requirements.txt (line 56))Setting up fonts-droid-fallback (1:6.0.1r16-1.1) ...Collecting ptyprocess==0.6.0 (from -r requirements.txt (line 48))Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/fonts.css'Receiving objects: 18% (1003/5570) Stored in directory: /root/.cache/pip/wheels/a9/c0/1e/32b694059fabeb7a9bcd2c65091ca875cd78ec1f54f47ea03bGet:37 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libva2 amd64 2.1.0-3 [47.6 kB]Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/changelists.css'23% [6 apache2-bin 2611 B/1071 kB 0%] 85% |███████████████████████████▎ | 788kB 5.9MB/s eta 0:00:01 (Reading database ... 33040 files and directories currently installed.)Reading package lists... 56% mesa-vdpau-drivers netpbm optipng poppler-data python3-olefile python3-pil python3-pyocr tesseract-ocr tesseract-ocr-eng 22% |███████ | 1.6MB 5.9MB/s eta 0:00:01 21% [Waiting for headers] Preparing to unpack .../140-vdpau-driver-all_1.1.1-3ubuntu1_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/th.js'Preparing to unpack .../108-libnetpbm10_2%3a10.0-15.3build1_amd64.deb ...update-alternatives: using /usr/bin/import-im6.q16 to provide /usr/bin/import (import) in auto mode Downloading https://files.pythonhosted.org/packages/d7/ca/3c74396a9ed8a4cfab5459800edeef9a1269591cb21f5a49bd71a49c5fa2/filelock-3.92% [18 Packages store 0 B] 29% [10 Sources 2531 kB/9051 kB 28%] [Waiting for headers] Extracting templates from packages: 63%HTTP request sent, awaiting response... 2019-01-20 19:50:06 (35.8 MB/s) - ‘lxc-install.sh’ saved [3054/3054]93% [18 Packages store 0 B] [27 Translation-en 0 B/182 kB 0%] 81% |██████████████████████████ | 1.6MB 6.0MB/s eta 0:00:01 44% [83 libavcodec57 4059 B/4592 kB 0%] 3755 kB/s 10sGet:54 http://archive.ubuntu.com/ubuntu bionic/main amd64 libgdk-pixbuf2.0-common all 2.36.11-2 [4536 B]43% [82 libzvbi0 4061 B/235 kB 2%] 3755 kB/s 10s96% [Waiting for headers] 4944 kB/s 0s 51% |████████████████▍ | 4.1MB 6.0MB/s eta 0:00:01 Get:88 http://archive.ubuntu.com/ubuntu bionic/main amd64 libvorbisfile3 amd64 1.3.5-4.2 [16.0 kB] .9.0-py2.py3-none-any.whl (112kB)Setting up gcc (4:7.3.0-3ubuntu2.1) ...Setting up libavformat57:amd64 (7:3.4.4-0ubuntu0.18.04.1) ...Unpacking libmpc3:amd64 (1.1.0-1) ...Preparing to unpack .../066-libspeex1_1.2~rc1.2-1ubuntu2_amd64.deb ...Unpacking python3.6-venv (3.6.7-1~18.04) ...Preparing to unpack .../071-libvorbis0a_1.3.5-4.2_amd64.deb ...7% [11 liblcms2-2 2613 B/139 kB 2%] Setting up libjbig2dec0:amd64 (0.13-6) ...Preparing to unpack .../35-libfakeroot_1.22-2ubuntu1_amd64.deb ...bms@pingu:~$ 5% [7 libc6-dev 4059 B/2587 kB 0%] Applying contenttypes.0001_initial... OKEnabling module authn_core.24% [32 gsfonts 1163 B/3120 kB 0%] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/fonts/Roboto-Regular-webfont.woff'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/inlines.min.js'update-alternatives: using /usr/bin/fakeroot-sysv to provide /usr/bin/fakeroot (fakeroot) in auto mode92% [Waiting for headers] 42% [31 dpkg-dev 2613 B/608 kB 0%] 4081 kB/s 12s 100% |████████████████████████████████| 235kB 2.8MB/s Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/es.js'Get:111 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libnss3 amd64 2:3.35-2ubuntu2.1 [1135 kB] Running setup.py bdist_wheel for pytest-sugar ... -4% [Waiting for headers] 81% |██████████████████████████ | 6.6MB 6.0MB/s eta 0:00:01 update-alternatives: using /usr/bin/composite-im6.q16 to provide /usr/bin/composite (composite) in auto modeCollecting pytest==3.9.3 (from -r requirements.txt (line 60))31% [Working] Enabling module mpm_event.Regenerating fonts cache... done. 80% |█████████████████████████▉ | 5.7MB 5.9MB/s eta 0:00:01 Unpacking libgcc-7-dev:amd64 (7.3.0-27ubuntu1~18.04) ...Get:16 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libmagickcore-6.q16-3 amd64 8:6.9.7.4+dfsg-16ubuntu6.4 [1616 kB] 100% |████████████████████████████████| 61kB 4.5MB/s 97% [19 Translation-en store 0 B] 4229 kB/s 0sSetting up mesa-va-drivers:amd64 (18.0.5-0ubuntu0~18.04.1) ...Setting up libjpeg8:amd64 (8c-2ubuntu8) ...Preparing to unpack .../036-libva2_2.1.0-3_amd64.deb ...4% [Working] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/fonts/Roboto-Light-webfont.woff'Get:76 http://archive.ubuntu.com/ubuntu bionic/main amd64 libwebp6 amd64 0.6.1-2 [185 kB] Get:36 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libaacs0 amd64 0.9.0-1 [51.4 kB]Selecting previously unselected package python3-venv. 100% |████████████████████████████████| 768kB 1.2MB/s Preparing to unpack .../050-libopenjp2-7_2.3.0-1_amd64.deb ...52% [91 libavformat57 1165 B/949 kB 0%] 3755 kB/s 8s 96% |██████████████████████████████▉ | 7.8MB 5.9MB/s eta 0:00:01 Preparing to unpack .../002-libfontconfig1_2.12.6-0ubuntu2_amd64.deb ...29% [Waiting for headers] Unpacking libmp3lame0:amd64 (3.100-2) ...Selecting previously unselected package cpp-7.14% [Waiting for headers] Collecting alabaster==0.7.12 (from -r requirements.txt (line 2))Unpacking i965-va-driver:amd64 (2.1.0-0ubuntu1) ...44% [Waiting for headers] 4081 kB/s 12sSelecting previously unselected package build-essential. Running setup.py bdist_wheel for termcolor ... -Receiving objects: 100% (5570/5570), 6.39 MiB | 3.49 MiB/s, done.Selecting previously unselected package libmpc3:amd64.Reading package lists... 97% * Documentation: https://help.ubuntu.comCollecting django-extensions==2.1.3 (from -r requirements.txt (line 16)) 100% |████████████████████████████████| 348kB 2.2MB/s 85% |███████████████████████████▎ | 6.9MB 5.8MB/s eta 0:00:01 Setting up tesseract-ocr-osd (4.00~git24-0e00fe6-1.2) ...Collecting pyparsing==2.3.0 (from -r requirements.txt (line 53))Get:96 http://archive.ubuntu.com/ubuntu bionic/main amd64 libdrm-amdgpu1 amd64 2.4.91-2 [19.0 kB] Preparing to unpack .../proftpd-doc_1.3.5e-1build1_all.deb ...92% [135 tesseract-ocr-eng 2611 B/1588 kB 0%] 4630 kB/s 1s Running setup.py bdist_wheel for termcolor ... doneDone.Setting up libgraphite2-3:amd64 (1.3.11-2) ... 1% |▌ | 122kB 1.1MB/s eta 0:00:08 Selecting previously unselected package libthai-data.Unpacking libavcodec57:amd64 (7:3.4.4-0ubuntu0.18.04.1) ...Setting up python3-olefile (0.45.1-1) ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/docs/js/api.js'Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 fonts-dejavu-core all 2.37-1 [1041 kB]Selecting previously unselected package liblua5.2-0:amd64.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ja.js' 12% |████ | 880kB 5.8MB/s eta 0:00:02 .5.1-py2.py3-none-any.whl Not uninstalling certifi at /usr/lib/python3/dist-packages, outside environment /usrSetting up libcupsfilters1:amd64 (1.20.2-0ubuntu3) ...84% [Waiting for headers] 4630 kB/s 2s 92% |█████████████████████████████▋ | 1.8MB 6.0MB/s eta 0:00:01 Applying documents.0018_auto_20170715_1712... OKGet:8 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 apache2-data all 2.4.29-1ubuntu4.5 [160 kB] 58% |██████████████████▉ | 4.8MB 5.8MB/s eta 0:00:01 Selecting previously unselected package python3-lib2to3.89% [Waiting for headers] 4630 kB/s 1sResolving deltas: 35% (1255/3560) 0 upgraded, 141 newly installed, 0 to remove and 19 not upgraded.Selecting previously unselected package python3-olefile. i965-va-driver imagemagick-6-common imagemagick-6.q16 libaacs0 libavahi-client3 libavahi-common-data libavahi-common3Unpacking apache2 (2.4.29-1ubuntu4.5) ...update-alternatives: using /usr/bin/animate-im6.q16 to provide /usr/bin/animate-im6 (animate-im6) in auto modeSelecting previously unselected package libgs9:amd64. 18% |██████ | 1.5MB 4.8MB/s eta 0:00:02 37% [Waiting for headers] Unpacking libva2:amd64 (2.1.0-3) ...Preparing to unpack .../120-libx11-xcb1_2%3a1.6.4-3ubuntu0.1_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/js/default.js'Get:110 http://archive.ubuntu.com/ubuntu bionic/main amd64 libnspr4 amd64 2:4.18-1ubuntu1 [112 kB] 68% [105 libllvm6.0 8630 kB/14.5 MB 59%] 3755 kB/s 5sSelecting previously unselected package libtiff5:amd64.Setting up liblqr-1-0:amd64 (0.4.2-2.1) ... libgomp1 libgraphite2-3 libgs9 libgs9-common libgsm1 libharfbuzz0b libijs-0.35 libilmbase12 libjbig0 libjbig2dec0 libjpeg-turbo8 61% |███████████████████▋ | 5.0MB 5.7MB/s eta 0:00:01 -py2.py3-none-any.whl (506kB).1-py3-none-any.whl (764kB)Setting up librsvg2-common:amd64 (2.40.20-2) ...Selecting previously unselected package libpython3-dev:amd64.Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.woff2'90% [18 Packages store 0 B] Preparing to unpack .../47-python3.6-dev_3.6.7-1~18.04_amd64.deb ... 60% |███████████████████▍ | 204kB 6.0MB/s eta 0:00:01 9% |███ | 686kB 5.9MB/s eta 0:00:02 92% [18 Packages store 0 B] [26 Packages 2687 B/489 kB 1%] 38% [Waiting for headers] 3755 kB/s 11sSelecting previously unselected package libpixman-1-0:amd64.Unpacking libvpx5:amd64 (1.7.0-3) ...Preparing to unpack .../004-fonts-droid-fallback_1%3a6.0.1r16-1.1_all.deb ...Setting up libavutil55:amd64 (7:3.4.4-0ubuntu0.18.04.1) ...Preparing to unpack .../111-libpaper-utils_1.1.24+nmu5ubuntu1_amd64.deb ... """)Unpacking imagemagick-6-common (8:6.9.7.4+dfsg-16ubuntu6.4) ...Unpacking apache2-utils (2.4.29-1ubuntu4.5) ...98% [139 i965-va-driver 2613 B/925 kB 0%] 4630 kB/s 0s.0-py2.py3-none-any.whl (57kB)Get:51 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-keyring all 10.6.0-1 [26.7 kB] Enabling conf other-vhosts-access-log. 5% |█▊ | 389kB 5.8MB/s eta 0:00:02 Collecting docopt==0.6.2 (from -r requirements.txt (line 20))4% [6 linux-libc-dev 2612 B/1010 kB 0%] 87% |████████████████████████████ | 2.7MB 5.8MB/s eta 0:00:01 Selecting previously unselected package libxcb-xfixes0:amd64.96% [18 Packages store 0 B] 76% [106 libopenexr22 2613 B/560 kB 0%] 3755 kB/s 4sSetting up binutils-common:amd64 (2.30-21ubuntu1~18.04) ...11% [Working] Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.ttf' 84% |███████████████████████████ | 2.6MB 6.0MB/s eta 0:00:01 Applying auth.0007_alter_validators_add_error_messages... OKExtracting templates from packages: 51% exitGet:28 http://archive.ubuntu.com/ubuntu bionic/main amd64 libpaper1 amd64 1.1.24+nmu5ubuntu1 [13.6 kB]Selecting previously unselected package libquadmath0:amd64.52% [90 libssh-gcrypt-4 2613 B/171 kB 2%] 3755 kB/s 8sGet:65 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libshine3 amd64 3.1.1-1 [22.9 kB]Setting up liblcms2-2:amd64 (2.9-1ubuntu0.1) ...57% [43 libpython3.6-dev 9668 kB/44.8 MB 22%] 4081 kB/s 9s Memory usage: 7% IP address for lxdbr0: 10.69.143.1 Applying documents.0010_log... OKCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/base.css'Setting up hicolor-icon-theme (0.17-2) ...39% [27 g++-7 5580 kB/7570 kB 74%] 4081 kB/s 13sGet:17 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libmagickwand-6.q16-3 amd64 8:6.9.7.4+dfsg-16ubuntu6.4 [293 kB]Get:47 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-crypto amd64 2.6.1-8ubuntu2 [244 kB] Get:15 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libatomic1 amd64 8.2.0-1ubuntu2~18.04 [9064 B]util-2.7.5-py2.py3-none-any.whl (225kB)Unpacking libxrender1:amd64 (1:0.9.10-1) ... 15% |████▉ | 1.1MB 5.9MB/s eta 0:00:02 40% |████████████▉ | 307kB 5.8MB/s eta 0:00:01 gcc-7-base libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libasan4 libatomic1 libbinutils libc-dev-binCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-yes.svg' 95% |██████████████████████████████▌ | 7.7MB 5.9MB/s eta 0:00:01 Preparing to unpack .../03-libaprutil1-ldap_1.6.1-2_amd64.deb ...Processing triggers for ureadahead (0.100.0-20) ... 80% |█████████████████████████▋ | 6.5MB 6.0MB/s eta 0:00:01 1% [Working] 71% [43 libpython3.6-dev 24.8 MB/44.8 MB 55%] 4611 kB/s 5s Running setup.py bdist_wheel for tzlocal ... -8% [Waiting for headers] 53% [Waiting for headers] 3755 kB/s 8sSetting up libtheora0:amd64 (1.1.1+dfsg.1-14) ...Unpacking libbluray2:amd64 (1:1.0.2-3) ...Setting up libavcodec57:amd64 (7:3.4.4-0ubuntu0.18.04.1) ...Selecting previously unselected package liblsan0:amd64.Selecting previously unselected package libaacs0:amd64.29% [Waiting for headers] Receiving objects: 76% (4234/5570), 4.67 MiB | 3.10 MiB/s update-alternatives: using /usr/bin/convert-im6.q16 to provide /usr/bin/convert-im6 (convert-im6) in auto modeSelecting previously unselected package libmpg123-0:amd64.bms@pingu:~$ exi 63% |████████████████████▍ | 1.7MB 6.0MB/s eta 0:00:01 Selecting previously unselected package liblept5.mmer-1.2.1-py2.py3-none-any.whl (64kB)Get:97 http://archive.ubuntu.com/ubuntu bionic/main amd64 libpciaccess0 amd64 0.14-1 [17.9 kB] Unpacking libdjvulibre-text (3.5.27.1-8) ...Selecting previously unselected package va-driver-all:amd64.Unpacking libpangoft2-1.0-0:amd64 (1.40.14-1ubuntu0.1) ...39% [10 Sources 5845 kB/9051 kB 65%] Selecting previously unselected package libmpx2:amd64. Downloading https://files.pythonhosted.org/packages/10/e0/27850afcb1683561c42db7c20e897cd5eb75b24843d574d8ec1389da4d49/fuzzywuzzy- 92% |█████████████████████████████▊ | 471kB 5.9MB/s eta 0:00:01 Collecting decorator==4.3.0 (from -r requirements.txt (line 13)) 99% |███████████████████████████████▊| 757kB 6.4MB/s eta 0:00:01 Preparing to unpack .../22-libgcc-7-dev_7.3.0-27ubuntu1~18.04_amd64.deb ...0.6.2.tar.gzGet:30 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libdpkg-perl all 1.19.0.5ubuntu2.1 [211 kB] Email address: e 64% |████████████████████▊ | 5.3MB 5.9MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/selector-icons.svg'Unpacking libjpeg8:amd64 (8c-2ubuntu8) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/timeparse.js' Applying auth.0002_alter_permission_name_max_length... OKSetting up python3-pil:amd64 (5.1.0-1) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ca.js'Collecting pickleshare==0.7.5 (from -r requirements.txt (line 43))22% [Waiting for headers] .1 pytest-xdist-1.24.0 python-dateutil-2.7.5 python-dotenv-0.9.1 python-gnupg-0.4.3 python-levenshtein-0.12.0 pytz-2018.7 regex-2018Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/css/bootstrap-tweaks.css'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-alert.svg'Fetched 1818 kB in 1s (2310 kB/s) Setting up libshine3:amd64 (3.1.1-1) ...-py2.py3-none-any.whl (8.1MB)Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/xregexp/xregexp.js'Setting up libtwolame0:amd64 (0.3.13-3) ...Preparing to unpack .../43-libpython3-dev_3.6.7-1~18.04_amd64.deb ...Get:137 http://archive.ubuntu.com/ubuntu bionic/universe amd64 tesseract-ocr amd64 4.00~git2288-10f4998a-2 [218 kB] Downloading https://files.pythonhosted.org/packages/6c/9d/c0feec696b815708354a2fd06ae0f51330a15043822a29bc8be2f185d9fe/Django-2.0. 7% |██▍ | 614kB 2.8MB/s eta 0:00:03 39% [Waiting for headers] 3755 kB/s 11s18% [29 libgs9-common 2852 kB/5094 kB 56%] ib_websupport-1.1.0-py2.py3-none-any.whlGet:60 http://archive.ubuntu.com/ubuntu bionic/main amd64 libgraphite2-3 amd64 1.3.11-2 [78.7 kB]Selecting previously unselected package libitm1:amd64.Unpacking apache2-data (2.4.29-1ubuntu4.5) ...Preparing to unpack .../38-libalgorithm-diff-xs-perl_0.04-5_amd64.deb ...py_forms-1.7.2-py2.py3-none-any.whl (105kB) 90% |█████████████████████████████ | 583kB 5.9MB/s eta 0:00:01 Setting up libxcb-render0:amd64 (1.13-1) ...Unpacking libx11-xcb1:amd64 (2:1.6.4-3ubuntu0.1) ... 81% |██████████████████████████ | 2.5MB 6.0MB/s eta 0:00:01 20% [Waiting for headers] Selecting previously unselected package libgomp1:amd64.14% [Waiting for headers] 35% [Working] 54% [93 libcupsfilters1 2613 B/108 kB 2%] 3755 kB/s 8sCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/gis/move_vertex_off.svg'Selecting previously unselected package libvorbis0a:amd64.64% [10 Sources store 0 B] [18 Packages 5094 kB/8570 kB 59%]hon-genutils-0.2.0 jedi-0.13.1 langdetect-1.0.7 more-itertools-4.3.0 packaging-18.0 parso-0.3.1 pdftotext-2.1.1 pexpect-4.6.0 picklenshtein-0.12.0.tar.gz (48kB)33% [51 libopenjp2-7 2613 B/145 kB 2%] Setting up libgdk-pixbuf2.0-0:amd64 (2.36.11-2) ...9-py3-none-any.whl (7.1MB)98% [54 python3-setuptools 4061 B/248 kB 2%] 4944 kB/s 0snsions-2.1.3-py2.py3-none-any.whl (216kB)0.15.0-py2.py3-none-any.whl 36% |███████████▌ | 2.6MB 6.0MB/s eta 0:00:01 Setting up libpoppler-dev:amd64 (0.62.0-2ubuntu2.5) ... 86% |███████████████████████████▋ | 7.0MB 6.0MB/s eta 0:00:01 Get:130 http://archive.ubuntu.com/ubuntu bionic/main amd64 netpbm amd64 2:10.0-15.3build1 [1017 kB] 61% |███████████████████▊ | 1.9MB 6.0MB/s eta 0:00:01 Setting up libthai0:amd64 (0.1.27-2) ...Fetched 3273 kB in 1s (3711 kB/s) Copying '/usr/local/lib/python3.6/dist-packages/django_extensions/static/django_extensions/js/jquery.bgiframe.js'78% [Waiting for headers] 3755 kB/s 3s81% [119 libtesseract4 2611 B/1163 kB 0%] 4630 kB/s 2s 91% |█████████████████████████████▍ | 1.8MB 5.9MB/s eta 0:00:01 Adding new user `ftp' (UID 112) with group `nogroup' ...Copying '/home/paperless/paperless/src/documents/static/documents/img/jpg.png'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/id.js' 36% |███████████▊ | 3.0MB 6.0MB/s eta 0:00:01 Selecting previously unselected package libllvm6.0:amd64.Setting up vdpau-driver-all:amd64 (1.1.1-3ubuntu1) ...Setting up libmpx2:amd64 (8.2.0-1ubuntu2~18.04) ... 95% |██████████████████████████████▋ | 204kB 6.0MB/s eta 0:00:01 Selecting previously unselected package python3-pyocr.Unpacking libshine3:amd64 (3.1.1-1) ... 16% |█████▍ | 92kB 5.8MB/s eta 0:00:01 Unpacking libapache2-mod-wsgi-py3 (4.5.17-1) ...Fetched 64.4 MB in 15s (4211 kB/s) Selecting previously unselected package netpbm.90% [18 Packages store 0 B] [20 Packages 4135 B/151 kB 3%] Requirement already satisfied: markupsafe==1.0 in /usr/lib/python3/dist-packages (from -r requirements.txt (line 37))Get:68 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libsoxr0 amd64 0.1.2-3 [65.9 kB]Selecting previously unselected package libdjvulibre21:amd64. 99% |███████████████████████████████▊| 8.0MB 5.8MB/s eta 0:00:01 Get:6 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 linux-libc-dev amd64 4.15.0-43.46 [1010 kB]Setting up libijs-0.35:amd64 (0.35-13) ...Setting up libmagickwand-6.q16-3:amd64 (8:6.9.7.4+dfsg-16ubuntu6.4) ....11.2 requests-2.20.0 snowballstemmer-1.2.1 sphinx-1.8.1 sphinxcontrib-websupport-1.1.0 termcolor-1.1.0 text-unidecode-1.2 toml-0.10Preparing to unpack .../006-libgomp1_8.2.0-1ubuntu2~18.04_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/popup_response.js' Running setup.py bdist_wheel for regex ... done Downloading https://files.pythonhosted.org/packages/4a/87/76ead690afc4c7710012ede242537cd9807dde9de6299e65d075925c0b02/python_gnupCollecting jedi==0.13.1 (from -r requirements.txt (line 34))Setting up libsoxr0:amd64 (0.1.2-3) ...Setting up libjpeg-turbo8:amd64 (1.5.2-0ubuntu5.18.04.1) ...Get:4 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 binutils amd64 2.30-21ubuntu1~18.04 [3392 B]Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/cs.js'94% [Waiting for headers] 4630 kB/s 0sGet:43 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpython3.6-dev amd64 3.6.7-1~18.04 [44.8 MB] 100% |████████████████████████████████| 153kB 3.3MB/s 97% [18 Packages store 0 B] 1.0.tar.gzSetting up libwebpmux3:amd64 (0.6.1-2) ... 92% |█████████████████████████████▌ | 81kB 6.1MB/s eta 0:00:01 Enabling conf serve-cgi-bin. 74% |████████████████████████ | 481kB 6.0MB/s eta 0:00:01 Running setup.py bdist_wheel for pdftotext ... | 33% |██████████▋ | 2.4MB 6.0MB/s eta 0:00:01 Setting up unpaper (6.1-2) ...Package apache2 is not configured yet. Will defer actions by package libapache2-mod-wsgi-py3. 53% |█████████████████ | 1.4MB 6.0MB/s eta 0:00:01 Setting up tesseract-ocr-eng (4.00~git24-0e00fe6-1.2) ...Get:22 http://archive.ubuntu.com/ubuntu bionic-updates/main Sources [231 kB]-2.4.0-py2.py3-none-any.whl (62kB)update-alternatives: using /usr/bin/mogrify-im6.q16 to provide /usr/bin/mogrify-im6 (mogrify-im6) in auto modeSetting up libpangoft2-1.0-0:amd64 (1.40.14-1ubuntu0.1) ...Get:7 http://archive.ubuntu.com/ubuntu bionic/main amd64 libc6-dev amd64 2.27-3ubuntu1 [2587 kB]2% [3 libfontconfig1 4061 B/137 kB 3%] libx11-xcb1 libx264-152 libx265-146 libxcb-dri2-0 libxcb-dri3-0 libxcb-present0 libxcb-render0 libxcb-shm0 libxcb-sync1Unpacking python3-setuptools (39.0.1-2) ...Selecting previously unselected package libbinutils:amd64.Preparing to unpack .../50-python3-keyring_10.6.0-1_all.deb ...16.1.0-py2.py3-none-any.whl (1.9MB)Selecting previously unselected package libilmbase12:amd64.Get:118 http://archive.ubuntu.com/ubuntu bionic/main amd64 libsensors4 amd64 1:3.4.0-4 [28.8 kB] Copying '/home/paperless/paperless/src/documents/static/documents/img/image.png'Selecting previously unselected package libpoppler-cpp-dev:amd64.Setting up libmpc3:amd64 (1.1.0-1) ...Creating home directory `/home/ftpupload' ...Get:9 http://security.ubuntu.com/ubuntu bionic-security/universe Sources [29.4 kB] 56% [10 Sources store 0 B] [18 Packages 2234 kB/8570 kB 26%] Unpacking dh-python (3.20180325ubuntu2) ... 100% |████████████████████████████████| 1.9MB 510kB/s Running setup.py bdist_wheel for pytest-sugar ... doneSetting up liblept5 (1.75.3-3) ...Receiving objects: 23% (1282/5570), 676.01 KiB | 1.30 MiB/s Get:40 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libva-x11-2 amd64 2.1.0-3 [11.5 kB]Unpacking libdatrie1:amd64 (0.2.10-7) ...Setting up libspeex1:amd64 (1.2~rc1.2-1ubuntu2) ...97% [19 Translation-en store 0 B] 4229 kB/s 0s Get:40 http://archive.ubuntu.com/ubuntu bionic/main amd64 libalgorithm-merge-perl all 0.08-3 [12.0 kB] 30% |█████████▊ | 2.5MB 5.8MB/s eta 0:00:01 72% |███████████████████████▍ | 614kB 6.0MB/s eta 0:00:01 Unpacking manpages-dev (4.15-1) ...After this operation, 247 MB of additional disk space will be used.32% [Waiting for headers] Get:123 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxcb-dri3-0 amd64 1.13-1 [6536 B] Get:112 http://archive.ubuntu.com/ubuntu bionic/main amd64 libpaper-utils amd64 1.1.24+nmu5ubuntu1 [8170 B] 97% |███████████████████████████████▏| 348kB 6.1MB/s eta 0:00:01 Downloading https://files.pythonhosted.org/packages/f8/0e/2365ddc010afb3d79147f1dd544e5ee24bf4ece58ab99b16fbb465ce6dc0/pytz-2018.733% [52 libopus0 2613 B/159 kB 2%] 3% |█▏ | 112kB 6.4MB/s eta 0:00:01 Preparing to unpack .../113-libpoppler-cpp0v5_0.62.0-2ubuntu2.5_amd64.deb ... 79% |█████████████████████████▎ | 604kB 5.9MB/s eta 0:00:01 8% [16 libmagickcore-6.q16-3 2611 B/1616 kB 0%] Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.woff' 24% |████████ | 1.8MB 6.0MB/s eta 0:00:01 Preparing to unpack .../038-libxfixes3_1%3a5.0.3-1_amd64.deb ...Setting up libxcb-xfixes0:amd64 (1.13-1) ...Setting up python3-venv (3.6.7-1~18.04) ...Setting up python3.6-dev (3.6.7-1~18.04) ...6% [Waiting for headers] Setting up libx11-xcb1:amd64 (2:1.6.4-3ubuntu0.1) ...Get:27 http://archive.ubuntu.com/ubuntu bionic-updates/main Translation-en [182 kB]Get:117 http://archive.ubuntu.com/ubuntu bionic/main amd64 librsvg2-common amd64 2.40.20-2 [5124 B] Unpacking libvorbisenc2:amd64 (1.3.5-4.2) ...Setting up libdrm-intel1:amd64 (2.4.91-2) ...78% [111 libnss3 2611 B/1135 kB 0%] 3755 kB/s 3s Downloading https://files.pythonhosted.org/packages/7c/17/9b7b6cddfd255388b58c61e25b091047f6814183e1d63741c8df8dcd65a2/virtualenv-Collecting inotify-simple==1.1.8 (from -r requirements.txt (line 31)) 9% |███▏ | 81kB 4.8MB/s eta 0:00:01 Unpacking python-pip-whl (9.0.1-2.3~ubuntu1) ...Setting up libchromaprint1:amd64 (1.4.3-1) ...Unpacking libx265-146:amd64 (2.6-3) ...Selecting previously unselected package python3-wheel.Selecting previously unselected package libgraphite2-3:amd64.Not creating home directory `/run/proftpd'. Downloading https://files.pythonhosted.org/packages/9a/41/220f49aaea88bc6fa6cba8d05ecf24676326156c23b991e80b3f2fc24c77/pickleshareCopying '/home/paperless/paperless/src/documents/static/documents/img/gif.png' 5% |█▋ | 419kB 3.1MB/s eta 0:00:03 nvidia-vdpau-driver nvidia-legacy-340xx-vdpau-driver 25% |████████▎ | 696kB 5.9MB/s eta 0:00:01 Unpacking libasan4:amd64 (7.3.0-27ubuntu1~18.04) ...Regenerating fonts cache... Get:50 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-secretstorage all 2.3.1-2 [12.1 kB] Preparing to unpack .../014-imagemagick-6-common_8%3a6.9.7.4+dfsg-16ubuntu6.4_all.deb ...Preparing to unpack .../069-libtheora0_1.1.1+dfsg.1-14_amd64.deb ... * MicroK8s is Kubernetes in a snap. Made by devs for devs.67% [4 proftpd-doc 4059 B/1165 kB 0%] Get:42 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libavutil55 amd64 7:3.4.4-0ubuntu0.18.04.1 [190 kB]Collecting fuzzywuzzy[speedup]==0.15.0 (from -r requirements.txt (line 27))Preparing to unpack .../058-libpango-1.0-0_1.40.14-1ubuntu0.1_amd64.deb ...remote: Compressing objects: 100% (12/12), done. 7% [Waiting for headers] Unpacking python3-pil:amd64 (5.1.0-1) ... Downloading https://files.pythonhosted.org/packages/3e/c7/3da685ef117d42ac8d71af525208759742dd235f8094221fdaafcd3dba8f/py-1.7.0-pyPreparing to unpack .../02-binutils-x86-64-linux-gnu_2.30-21ubuntu1~18.04_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/et.js'Setting up libswresample2:amd64 (7:3.4.4-0ubuntu0.18.04.1) ...Get:85 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libchromaprint1 amd64 1.4.3-1 [36.8 kB] _headers-2.4.0-py2.py3-none-any.whlUnpacking libavahi-client3:amd64 (0.7-3.1ubuntu1.1) ...Unpacking libcrystalhd3:amd64 (1:0.0~git20110715.fdd2f19-12) ...Get:78 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libx264-152 amd64 2:0.152.2854+gite9a5903-2 [609 kB] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ro.js' 53% |█████████████████ | 491kB 5.9MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/prepopulate.js' 100% |████████████████████████████████| 2.7MB 387kB/s Unpacking libisl19:amd64 (0.19-1) ...13% [Waiting for headers] Running setup.py bdist_wheel for regex ... | 72% |███████████████████████▍ | 5.9MB 5.9MB/s eta 0:00:01 Collecting pytz==2018.7 (from -r requirements.txt (line 65)).0 pyocr-0.5.3 pyparsing-2.3.0 pytest-3.9.3 pytest-cov-2.6.0 pytest-django-3.4.3 pytest-env-0.6.2 pytest-forked-0.2 pytest-sugar-0.9 Found existing installation: requests 2.18.4Preparing to unpack .../00-binutils-common_2.30-21ubuntu1~18.04_amd64.deb ... 100% |████████████████████████████████| 71kB 3.5MB/s Get:20 http://archive.ubuntu.com/ubuntu bionic/main amd64 fonts-noto-mono all 20171026-2 [75.5 kB]16% [5 liblua5.2-0 2613 B/108 kB 2%] Site 000-default disabled.Preparing to unpack .../127-mesa-va-drivers_18.0.5-0ubuntu0~18.04.1_amd64.deb ...Get:139 http://archive.ubuntu.com/ubuntu bionic/universe amd64 i965-va-driver amd64 2.1.0-0ubuntu1 [925 kB] Setting up fakeroot (1.22-2ubuntu1) ...Selecting previously unselected package libbdplus0:amd64.Preparing to unpack .../08-libisl19_0.19-1_amd64.deb ...bms@FortBoyard:~$ ex Found existing installation: idna 2.6 One quick install on a workstation, VM, or appliance.Setting up libltdl7:amd64 (2.4.6-2) ...Receiving objects: 19% (1059/5570) 79% [43 libpython3.6-dev 33.0 MB/44.8 MB 74%] 4611 kB/s 3sCopying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/img/grid.png'After this operation, 271 MB of additional disk space will be used. 26% |████████▋ | 204kB 6.0MB/s eta 0:00:01 72% |███████████████████████▎ | 368kB 5.9MB/s eta 0:00:01 Get:41 http://archive.ubuntu.com/ubuntu bionic/main amd64 libexpat1-dev amd64 2.2.5-3 [122 kB] 100% |████████████████████████████████| 61kB 3.7MB/s Preparing to unpack .../07-apache2-data_2.4.29-1ubuntu4.5_all.deb ...Preparing to unpack .../015-libmagickcore-6.q16-3_8%3a6.9.7.4+dfsg-16ubuntu6.4_amd64.deb ...Unpacking libva-x11-2:amd64 (2.1.0-3) ...8% [Waiting for headers] Setting up libasan4:amd64 (7.3.0-27ubuntu1~18.04) ...Setting up libgif7:amd64 (5.1.4-2) ...Get:28 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [711 kB]Preparing to unpack .../123-libxcb-present0_1.13-1_amd64.deb ...31% [10 Sources 2968 kB/9051 kB 33%] Get:44 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxcb-render0 amd64 1.13-1 [14.7 kB]Preparing to unpack .../138-i965-va-driver_2.1.0-0ubuntu1_amd64.deb ...Get:93 http://archive.ubuntu.com/ubuntu bionic/main amd64 libcupsfilters1 amd64 1.20.2-0ubuntu3 [108 kB] 14% |████▊ | 112kB 6.5MB/s eta 0:00:01 Selecting previously unselected package libxcb-render0:amd64.Setting up apache2 (2.4.29-1ubuntu4.5) ...Unpacking libitm1:amd64 (8.2.0-1ubuntu2~18.04) ... Downloading https://files.pythonhosted.org/packages/b8/ad/c6f60602d3ee3d92fbed87675b6fb6a6f9a38c223343ababdb44ba201f10/Babel-2.6.092% [18 Packages store 0 B] [25 Sources 2687 B/122 kB 2%] 97% |███████████████████████████████▏| 1.9MB 6.0MB/s eta 0:00:01 97% [18 Packages store 0 B] logoutSetting up libtsan0:amd64 (8.2.0-1ubuntu2~18.04) ... proftpd-mod-geoipGet:72 http://archive.ubuntu.com/ubuntu bionic/main amd64 libvorbis0a amd64 1.3.5-4.2 [86.4 kB] Setting up libgs9:amd64 (9.26~dfsg+0-0ubuntu0.18.04.3) ... systemctl reload apache2Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/README.txt'40% [Working] 3755 kB/s 10s 5% |█▉ | 112kB 6.4MB/s eta 0:00:01 Setting up python3-xdg (0.25-4ubuntu1) ...Selecting previously unselected package binutils.update-alternatives: using /usr/bin/identify-im6.q16 to provide /usr/bin/identify (identify) in auto modeSelecting previously unselected package libdatrie1:amd64. liblsan0-dbg libtsan0-dbg libubsan0-dbg libcilkrts5-dbg libmpx2-dbg libquadmath0-dbg glibc-doc bzr libstdc++-7-doc make-docSetting up libopenjp2-7:amd64 (2.3.0-1) ...Unpacking fontconfig-config (2.12.6-0ubuntu2) ...Unpacking libgdk-pixbuf2.0-common (2.36.11-2) ... 71% |██████████████████████▉ | 1.9MB 5.9MB/s eta 0:00:01 Unpacking fakeroot (1.22-2ubuntu1) ...Unpacking ssl-cert (1.0.39) ...5.1-cp36-cp36m-manylinux1_x86_64.whl (202kB) 26% |████████▌ | 512kB 5.9MB/s eta 0:00:01 Downloading https://files.pythonhosted.org/packages/09/51/9c48a46334be50c13d25a3afe55fa05c445699304c5ad32619de953a2305/parso-0.3.1 68% |█████████████████████▉ | 4.9MB 6.0MB/s eta 0:00:01 65% |█████████████████████ | 1.3MB 6.0MB/s eta 0:00:01 utils-0.2.0-py2.py3-none-any.whl libaprutil1-ldap liblua5.2-0 ssl-certCollecting more-itertools==4.3.0 (from -r requirements.txt (line 38)) 90% |█████████████████████████████ | 2.8MB 6.0MB/s eta 0:00:01 Selecting previously unselected package apache2..7.12-py2.py3-none-any.whl 42% |█████████████▌ | 3.4MB 2.6MB/s eta 0:00:02 38% [Waiting for headers] 31% [Working] Unpacking libavahi-common3:amd64 (0.7-3.1ubuntu1.1) ...Enabling module filter.32% [26 libstdc++-7-dev 4059 B/1463 kB 0%] Selecting previously unselected package libspeex1:amd64.32% [Waiting for headers] Unpacking libilmbase12:amd64 (2.2.0-11ubuntu2) ...Get:18 http://archive.ubuntu.com/ubuntu bionic/universe amd64 Packages [8570 kB]remote: Total 5570 (delta 9), reused 21 (delta 9), pack-reused 5549 Selecting previously unselected package libtsan0:amd64.2.0-py2.py3-none-any.whl (841kB)Unpacking libwebp6:amd64 (0.6.1-2) ... Downloading https://files.pythonhosted.org/packages/3a/e1/5f9023cc983f1a628a8c2fd051ad19e76ff7b142a0faf329336f9a62a514/attrs-18.2.Setting up fonts-noto-mono (20171026-2) ...Extracting templates from packages: 21% Not uninstalling pillow at /usr/lib/python3/dist-packages, outside environment /usrUnpacking python3.6-dev (3.6.7-1~18.04) ...Adding user paperless to group ftpuploadCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/lt.js' Downloading https://files.pythonhosted.org/packages/99/0b/d37a5a96c5d301e23adcabcc2f3fa659fb34e6308590f95ebb50cdbe98a1/djangorestfSelecting previously unselected package libwebp6:amd64. Downloading https://files.pythonhosted.org/packages/f9/6e/31efb8dc1d17052c12f39262223e94038bfcc4cc7a124235630a6d50f166/pytest-env-Unpacking proftpd-basic (1.3.5e-1build1) ...Setting up libnss3:amd64 (2:3.35-2ubuntu2.1) ...Preparing to unpack .../39-libalgorithm-merge-perl_0.08-3_all.deb ...Setting up libxvidcore4:amd64 (2:1.3.5-1) ... 100% |████████████████████████████████| 122kB 3.8MB/s Preparing to unpack .../107-libmagickcore-6.q16-3-extra_8%3a6.9.7.4+dfsg-16ubuntu6.4_amd64.deb ...Unpacking libpoppler-dev:amd64 (0.62.0-2ubuntu2.5) ... 99% |████████████████████████████████| 225kB 6.1MB/s eta 0:00:01 Setting up netpbm (2:10.0-15.3build1) ...2.6.0-py2.py3-none-any.whlSetting up libavahi-client3:amd64 (0.7-3.1ubuntu1.1) ...0-cp36-cp36m-manylinux1_x86_64.whl (2.0MB)Collecting backcall==0.1.0 (from -r requirements.txt (line 7))Adding new user `paperless' (1000) with group `paperless' ...2% [4 fontconfig 2613 B/169 kB 2%] Get:77 http://archive.ubuntu.com/ubuntu bionic/main amd64 libwebpmux3 amd64 0.6.1-2 [19.6 kB] 46% [Waiting for headers] 4081 kB/s 12sEnabling module env. 6% |██ | 204kB 6.0MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/xregexp/LICENSE-XREGEXP.txt'92% [18 Packages store 0 B] update-alternatives: using /usr/bin/stream-im6.q16 to provide /usr/bin/stream-im6 (stream-im6) in auto mode 88% |████████████████████████████▍ | 7.2MB 5.9MB/s eta 0:00:01 Creating home directory `/srv/ftp' ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.eot'Setting up libcups2:amd64 (2.2.7-1ubuntu2.3) ...Collecting text-unidecode==1.2 (from -r requirements.txt (line 73)) Applying auth.0009_alter_user_last_name_max_length... OKGet:27 http://archive.ubuntu.com/ubuntu bionic/main amd64 libjbig2dec0 amd64 0.13-6 [55.9 kB]2% [Waiting for headers] Setting up python-pip-whl (9.0.1-2.3~ubuntu1) ...Preparing to unpack .../131-python3-olefile_0.45.1-1_all.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/actions.js' Running setup.py bdist_wheel for pyocr ... \Selecting previously unselected package apache2-bin.t-1.24.0-py2.py3-none-any.whlSelecting previously unselected package libcroco3:amd64.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/jquery/jquery.min.js'Selecting previously unselected package libpaper-utils.Preparing to unpack .../005-libjpeg-turbo8_1.5.2-0ubuntu5.18.04.1_amd64.deb ...66% [43 libpython3.6-dev 19.2 MB/44.8 MB 43%] 4611 kB/s 6sCollecting filelock==3.0.10 (from -r requirements.txt (line 25)) Running setup.py bdist_wheel for langdetect ... /Reading package lists... Done 100% |████████████████████████████████| 122kB 3.6MB/s Selecting previously unselected package libdrm-intel1:amd64.Get:52 http://archive.ubuntu.com/ubuntu bionic/main amd64 libopus0 amd64 1.1.2-1ubuntu1 [159 kB]Preparing to unpack .../14-libatomic1_8.2.0-1ubuntu2~18.04_amd64.deb ... 13% |████▏ | 1.1MB 4.1MB/s eta 0:00:02 Get:11 http://archive.ubuntu.com/ubuntu bionic/main amd64 ssl-cert all 1.0.39 [17.0 kB]Setting up liblsan0:amd64 (8.2.0-1ubuntu2~18.04) ...Preparing to unpack .../054-libgdk-pixbuf2.0-0_2.36.11-2_amd64.deb ...Receiving objects: 5% (279/5570) Selecting previously unselected package g++-7.Unpacking libpython3.6-dev:amd64 (3.6.7-1~18.04) ...Preparing to unpack .../10-cpp-7_7.3.0-27ubuntu1~18.04_amd64.deb ... 41% |█████████████▍ | 1.3MB 6.0MB/s eta 0:00:01 Applying documents.0009_auto_20160214_0040... OKSelecting previously unselected package imagemagick-6.q16.Preparing to unpack .../libmemcachedutil2_1.0.18-4.2_amd64.deb ...Unpacking libwavpack1:amd64 (5.1.0-2ubuntu1.2) ... Downloading https://files.pythonhosted.org/packages/6e/fe/6e5b43eac75c617cd9383ce82dd76d08fa198a770b06986951b3086980c9/pytest_djan 28% |█████████▎ | 2.1MB 5.7MB/s eta 0:00:01 Get:10 http://archive.ubuntu.com/ubuntu bionic/universe Sources [9051 kB] Suggested packages: 10% |███▍ | 860kB 3.7MB/s eta 0:00:02 Get:32 http://archive.ubuntu.com/ubuntu bionic/main amd64 gsfonts all 1:8.11+urwcyr1.0.7~pre44-4.4 [3120 kB]Selecting previously unselected package libpangoft2-1.0-0:amd64.81% [Waiting for headers] 4630 kB/s 2s16% [Waiting for headers] 13% |████▍ | 972kB 5.8MB/s eta 0:00:02 33% [Working] Preparing to unpack .../21-libquadmath0_8.2.0-1ubuntu2~18.04_amd64.deb ...Setting up fontconfig (2.12.6-0ubuntu2) ... * Full K8s GPU support is now available!Collecting pygments==2.2.0 (from -r requirements.txt (line 51))Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/vendor/select2/select2.css' 80% |█████████████████████████▋ | 614kB 5.9MB/s eta 0:00:01 Collecting pluggy==0.8.0 (from -r requirements.txt (line 45))Receiving objects: 43% (2396/5570), 4.67 MiB | 3.10 MiB/s Setting up libmemcachedutil2:amd64 (1.0.18-4.2) ...Preparing to unpack .../021-libavahi-common3_0.7-3.1ubuntu1.1_amd64.deb ... 74% |████████████████████████ | 2.0MB 6.0MB/s eta 0:00:01 Preparing to unpack .../08-apache2_2.4.29-1ubuntu4.5_amd64.deb ... 21% |███████ | 215kB 5.2MB/s eta 0:00:01 Get:101 http://archive.ubuntu.com/ubuntu bionic/main amd64 libgdk-pixbuf2.0-bin amd64 2.36.11-2 [7864 B] Get:5 http://archive.ubuntu.com/ubuntu bionic/main amd64 liblua5.2-0 amd64 5.2.4-1.1build1 [108 kB]Unpacking apache2-bin (2.4.29-1ubuntu4.5) ...Receiving objects: 82% (4568/5570), 4.67 MiB | 3.10 MiB/s -py2.py3-none-any.whl79% [18 Packages store 0 B] [19 Translation-en 1119 kB/4941 kB 23%] Downloading https://files.pythonhosted.org/packages/93/d6/abcb22de61d78e2fc3959c964628a5771e47e7cc60d53e9342e21ed6cc9a/traitlets-4Selecting previously unselected package libavahi-client3:amd64.Selecting previously unselected package libvorbisfile3:amd64.Collecting atomicwrites==1.2.1 (from -r requirements.txt (line 4))29% [Waiting for headers] Setting up gsfonts (1:8.11+urwcyr1.0.7~pre44-4.4) ...go-3.4.3-py2.py3-none-any.whl Running setup.py bdist_wheel for langdetect ... -Selecting previously unselected package gcc.(Reading database ... 32033 files and directories currently installed.)Setting up libdpkg-perl (1.19.0.5ubuntu2.1) ... Applying documents.0005_auto_20160123_0313... OK99% [29 Translation-en store 0 B] 4229 kB/s 0supdate-alternatives: using /usr/bin/mogrify-im6.q16 to provide /usr/bin/mogrify (mogrify) in auto modeSetting up libxcb-dri2-0:amd64 (1.13-1) ...Setting up libavahi-common3:amd64 (0.7-3.1ubuntu1.1) ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/docs/img/grid.png'Setting up libx265-146:amd64 (2.6-3) ... Downloading https://files.pythonhosted.org/packages/62/94/5430ebaa83f91cc7a9f687ff5238e26164a779cca2ef9903232268b0a318/Pillow-5.3.bms@FortBoyard:~$ exit 34% |███████████ | 174kB 5.9MB/s eta 0:00:01 Get:12 http://archive.ubuntu.com/ubuntu bionic/main amd64 liblqr-1-0 amd64 0.4.2-2.1 [27.7 kB]Preparing to unpack .../061-libpangoft2-1.0-0_1.40.14-1ubuntu0.1_amd64.deb ...Get:66 http://archive.ubuntu.com/ubuntu bionic/main amd64 libsnappy1v5 amd64 1.1.7-1 [16.0 kB] libmemcached11 libmemcachedutil2 proftpd-docUnpacking python3-venv (3.6.7-1~18.04) ... Applying documents.0008_document_file_type... OKUnpacking libdrm-radeon1:amd64 (2.4.91-2) ...98% [138 unpaper 2613 B/242 kB 1%] 4630 kB/s 0sGet:4 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/zh-CN.js'Preparing to unpack .../09-libmpc3_1.1.0-1_amd64.deb ...44% [34 python3-distutils 2613 B/141 kB 2%] 4081 kB/s 12sConnecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.16.133|:443... connected.Processing triggers for libc-bin (2.27-3ubuntu1) ...Preparing to unpack .../24-gcc_4%3a7.3.0-3ubuntu2.1_amd64.deb ...Get:14 http://archive.ubuntu.com/ubuntu bionic/main amd64 libtiff5 amd64 4.0.9-5 [152 kB]Selecting previously unselected package libtesseract4.update-alternatives: using /usr/bin/montage-im6.q16 to provide /usr/bin/montage (montage) in auto modePreparing to unpack .../090-libavformat57_7%3a3.4.4-0ubuntu0.18.04.1_amd64.deb ...Get:86 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libgme0 amd64 0.6.2-1 [121 kB] Unpacking mesa-vdpau-drivers:amd64 (18.0.5-0ubuntu0~18.04.1) ...21% [Waiting for headers] Selecting previously unselected package python3.6-venv.Selecting previously unselected package libaprutil1-ldap:amd64. Downloading https://files.pythonhosted.org/packages/d1/29/605c2cc68a9992d18dada28206eeada56ea4bd07a239669da41674648b6f/ptyprocess- 10% |███▎ | 204kB 5.9MB/s eta 0:00:01 98% |███████████████████████████████▍| 174kB 6.0MB/s eta 0:00:01 Preparing to unpack .../136-tesseract-ocr_4.00~git2288-10f4998a-2_amd64.deb ...33% [Waiting for headers] Preparing to unpack .../05-linux-libc-dev_4.15.0-43.46_amd64.deb ... 56% |██████████████████ | 4.5MB 5.9MB/s eta 0:00:01 Extracting templates from packages: 100%Setting up libapr1:amd64 (1.6.3-2) ...Successfully installed alabaster-0.7.12 apipkg-1.5 atomicwrites-1.2.1 attrs-18.2.0 babel-2.6.0 backcall-0.1.0 certifi-2018.10.15 cov Downloading https://files.pythonhosted.org/packages/30/0a/1b009b525526cd3cd9f52f52391b426c5a3597447be811a10bcb1f6b05eb/pytest_cov-Preparing to unpack .../008-libjbig0_2.1-3.1build1_amd64.deb ...17% [Waiting for headers] Get:8 http://archive.ubuntu.com/ubuntu bionic/multiverse Sources [181 kB] Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/fontawesome-webfont.svg'Preparing to unpack .../044-libxcb-shm0_1.13-1_amd64.deb ...Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-43-generic x86_64) - https://bit.ly/microk8s.tar.gz Downloading https://files.pythonhosted.org/packages/8c/da/b8dd8deb741bff556db53902d4706774c8e1e67265f69528c14c003644e6/gunicorn-19Get:52 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-keyrings.alt all 3.0-1 [16.6 kB] Get:79 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libx265-146 amd64 2.6-3 [1026 kB] Preparing to unpack .../46-python3-crypto_2.6.1-8ubuntu2_amd64.deb ...Preparing to unpack .../092-libcupsfilters1_1.20.2-0ubuntu3_amd64.deb ...2% [5 fonts-droid-fallback 2611 B/1805 kB 0%] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/xregexp/xregexp.min.js' 49% |████████████████ | 4.0MB 6.0MB/s eta 0:00:01 Copying files from `/etc/skel' ...Selecting previously unselected package libpangocairo-1.0-0:amd64.update-alternatives: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto modeUnpacking libbinutils:amd64 (2.30-21ubuntu1~18.04) ...Setting up python3-pyocr (0.3.0-1) ... 58% |██████████████████▉ | 1.8MB 5.9MB/s eta 0:00:01 Get:13 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libcc1-0 amd64 8.2.0-1ubuntu2~18.04 [39.5 kB]Preparing to unpack .../115-libpoppler-cpp-dev_0.62.0-2ubuntu2.5_amd64.deb ... 9% |███▏ | 92kB 5.8MB/s eta 0:00:01 Unpacking libzvbi-common (0.2.35-13) ...Selecting previously unselected package libva-drm2:amd64.Unpacking fonts-noto-mono (20171026-2) ...Collecting execnet==1.5.0 (from -r requirements.txt (line 22))13% [11 cpp-7 2873 kB/6738 kB 43%] 87% |████████████████████████████ | 7.1MB 5.8MB/s eta 0:00:01 Downloading https://files.pythonhosted.org/packages/79/42/d717cc2b4520fb09e45b344b1b0b4e81aa672001dd128c180fabc655c341/text_unidec5% [6 libjpeg-turbo8 2613 B/110 kB 2%] libcupsfilters1 libcupsimage2 libdatrie1 libdjvulibre-text libdjvulibre21 libdrm-amdgpu1 libdrm-intel1 libdrm-nouveau237% [Waiting for headers] Preparing to unpack .../080-libzvbi-common_0.2.35-13_all.deb ...93% [18 Packages store 0 B] Get:6 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libjpeg-turbo8 amd64 1.5.2-0ubuntu5.18.04.1 [110 kB]Selecting previously unselected package libbluray2:amd64.Selecting previously unselected package librsvg2-2:amd64.8% [Working] 97% [Working] 4944 kB/s 0sSelecting previously unselected package libapr1:amd64.Selecting previously unselected package python3-pip.py2.py3-none-any.whlCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/eu.js'Get:105 http://archive.ubuntu.com/ubuntu bionic/main amd64 libllvm6.0 amd64 1:6.0-1ubuntu2 [14.5 MB] Selecting previously unselected package liblqr-1-0:amd64.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/responsive_rtl.css' 55% |█████████████████▊ | 4.0MB 6.0MB/s eta 0:00:01 Preparing to unpack .../096-libpciaccess0_0.14-1_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/img/glyphicons-halflings-white.png' 44% |██████████████▍ | 3.6MB 5.4MB/s eta 0:00:01 libdrm-radeon1 libfftw3-double3 libfontconfig1 libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-bin libgdk-pixbuf2.0-common libgif7 libgme0Get:103 http://archive.ubuntu.com/ubuntu bionic/main amd64 libilmbase12 amd64 2.2.0-11ubuntu2 [71.4 kB] 50% [84 libbluray2 2613 B/141 kB 2%] 3755 kB/s 9sGet:10 http://archive.ubuntu.com/ubuntu bionic/main amd64 libjpeg8 amd64 8c-2ubuntu8 [2194 B] Processes: 393update-alternatives: using /usr/bin/conjure-im6.q16 to provide /usr/bin/conjure (conjure) in auto modeSetting up libgme0:amd64 (0.6.2-1) ...Get:34 http://archive.ubuntu.com/ubuntu bionic-backports/universe Translation-en [1604 B]Preparing to unpack .../112-libpoppler73_0.62.0-2ubuntu2.5_amd64.deb ...Collecting regex==2018.11.2 (from -r requirements.txt (line 66))Processing triggers for man-db (2.8.3-2ubuntu0.1) ...Enabling module authz_host. Applying documents.0003_sender... OK99% [28 Packages store 0 B] 4229 kB/s 0sRunning migrations:Get:80 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libxvidcore4 amd64 2:1.3.5-1 [200 kB] Preparing to unpack .../125-libxcb-xfixes0_1.13-1_amd64.deb ...Unpacking libaprutil1:amd64 (1.6.1-2) ...77% [107 libwmf0.2-7 2613 B/150 kB 2%] 3755 kB/s 3sSelecting previously unselected package tesseract-ocr.Unpacking libogg0:amd64 (1.3.2-1) ...Get:46 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 python-pip-whl all 9.0.1-2.3~ubuntu1 [1652 kB] Unpacking libijs-0.35:amd64 (0.35-13) ...Collecting python-dotenv==0.9.1 (from -r requirements.txt (line 62)) automake libtool flex bison gdb gcc-doc gcc-7-multilib libgcc1-dbg libgomp1-dbg libitm1-dbg libatomic1-dbg libasan4-dbgt, python-dotenv, python-gnupg, snowballstemmer, sphinxcontrib-websupport, sphinx, toml, virtualenv, tox46% [Working] 4081 kB/s 12sCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/collapse.js'58% [105 libllvm6.0 1162 B/14.5 MB 0%] 3755 kB/s 7sPreparing to unpack .../37-libalgorithm-diff-perl_1.19.03-1_all.deb ...Get:18 http://archive.ubuntu.com/ubuntu bionic/main amd64 libogg0 amd64 1.3.2-1 [17.2 kB]update-alternatives: using /usr/bin/compare-im6.q16 to provide /usr/bin/compare-im6 (compare-im6) in auto modeSetting up libzvbi0:amd64 (0.2.35-13) ...Setting up imagemagick (8:6.9.7.4+dfsg-16ubuntu6.4) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/gis/move_vertex_on.svg'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/jquery/LICENSE-JQUERY.txt'Get:3 http://archive.ubuntu.com/ubuntu bionic/main amd64 libaprutil1-dbd-sqlite3 amd64 1.6.1-2 [10.6 kB]90% [Waiting for headers] 4630 kB/s 1sUnpacking libubsan0:amd64 (7.3.0-27ubuntu1~18.04) ... 76% |████████████████████████▌ | 1.5MB 12.4MB/s eta 0:00:01 Unpacking va-driver-all:amd64 (2.1.0-3) ...-py2.py3-none-any.whl (766kB)Unpacking g++-7 (7.3.0-27ubuntu1~18.04) ...al python-levenshtein Downloading https://files.pythonhosted.org/packages/89/d1/92e6df2e503a69df9faab187c684585f0136662c12bb1f36901d426f3fab/packaging-1 Downloading https://files.pythonhosted.org/packages/e5/b4/c6102d9dea6a4cbc5a56ebe5843c3123e5013c17a4f2f0f6d490d821766e/regex-2018.Successfully built backcall docopt filemagic inotify-simple langdetect pdftotext pyocr pytest-env pytest-sugar regex termcolor tzlocUnpacking gcc-7 (7.3.0-27ubuntu1~18.04) ... 84% |███████████████████████████▏ | 6.0MB 5.8MB/s eta 0:00:01 31% |██████████▏ | 2.6MB 4.0MB/s eta 0:00:02 92% [Working] 4630 kB/s 1s43% [Waiting for headers] 4081 kB/s 12sEnabling module autoindex. 48% |███████████████▋ | 3.5MB 6.0MB/s eta 0:00:01 95% [48 python3.6-dev 2613 B/508 kB 1%] 4944 kB/s 0s 98% |███████████████████████████████▋| 757kB 6.2MB/s eta 0:00:01 84% [Working] 4630 kB/s 2s44% [Working] 4081 kB/s 12sPreparing to unpack .../024-libcupsimage2_2.2.7-1ubuntu2.3_amd64.deb ...Unpacking liblua5.2-0:amd64 (5.2.4-1.1build1) ...1% [3 binutils-x86-64-linux-gnu 2611 B/1855 kB 0%] Unpacking gcc (4:7.3.0-3ubuntu2.1) ...Copying '/home/paperless/paperless/src/documents/static/js/colours.js'47% [41 libexpat1-dev 4061 B/122 kB 3%] 4081 kB/s 12sCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ar.js'Preparing to unpack .../033-imagemagick-6.q16_8%3a6.9.7.4+dfsg-16ubuntu6.4_amd64.deb ...Email address: Selecting previously unselected package libalgorithm-diff-xs-perl. 99% |███████████████████████████████▉| 1.9MB 5.9MB/s eta 0:00:01 Selecting previously unselected package libtheora0:amd64. 100% |████████████████████████████████| 645kB 1.3MB/s Downloading https://files.pythonhosted.org/packages/7e/9f/526a6947247599b084ee5232e4f9190a38f398d7300d866af3ab571a5bfe/wcwidth-0.1Setting up libcroco3:amd64 (0.6.12-2) ...Get:54 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-setuptools all 39.0.1-2 [248 kB] Running setup.py bdist_wheel for backcall ... doneSelecting previously unselected package libcupsfilters1:amd64. www-browser apache2-doc apache2-suexec-pristine | apache2-suexec-custom openssl-blacklist.0 tox-3.5.3 traitlets-4.3.2 tzlocal-1.5.1 urllib3-1.24.1 virtualenv-16.1.0 wcwidth-0.1.7Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/uk.js'Selecting previously unselected package libxcb-sync1:amd64.update-alternatives: using /usr/bin/import-im6.q16 to provide /usr/bin/import-im6 (import-im6) in auto modeSelecting previously unselected package binutils-x86-64-linux-gnu.97% [18 Packages store 0 B] Found existing installation: urllib3 1.228.10.15-py2.py3-none-any.whl (146kB)Preparing to unpack .../067-libsoxr0_0.1.2-3_amd64.deb ...Preparing to unpack .../01-libbinutils_2.30-21ubuntu1~18.04_amd64.deb ... 69% |██████████████████████▏ | 5.6MB 5.9MB/s eta 0:00:01 Preparing to unpack .../027-libpaper1_1.1.24+nmu5ubuntu1_amd64.deb ... Downloading https://files.pythonhosted.org/packages/42/a9/d1785c85ebf9b7dfacd08938dd028209c34a0ea3b1bcdb895208bd40a67d/python-Leve Swap usage: 0% IP address for virbr0: 192.168.122.1Preparing to unpack .../088-libopenmpt0_0.3.6-1_amd64.deb ...Collecting pdftotext==2.1.1 (from -r requirements.txt (line 41))17% [Waiting for headers] Downloading https://files.pythonhosted.org/packages/7a/1a/9bd24a185873b998611c2d8d4fb15cd5e8a879ead36355df7ee53e9111bf/jedi-0.13.1 Stored in directory: /root/.cache/pip/wheels/ae/1c/56/c27dc42b329eaf83222ba4f14c084489427e591a385b2209dc21% [Working] Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/js/jquery-3.3.1.min.js'74% [43 libpython3.6-dev 27.7 MB/44.8 MB 62%] 4611 kB/s 4s Downloading https://files.pythonhosted.org/packages/cc/7e/83ba784ad2b95317bbbed915f0888d7d1cd8dc3d2e4b8ddec8fbc4c3e800/django_corsSelecting previously unselected package libdrm-amdgpu1:amd64.Enabling module auth_basic.167 static files copied to '/home/paperless/paperless/static'. libsoxr0 libspeex1 libssh-gcrypt-4 libswresample2 libtesseract4 libthai-data libthai0 libtheora0 libtiff5 libtwolame0 libva-drm2 66% |█████████████████████▍ | 4.8MB 5.2MB/s eta 0:00:01 Get:3 http://archive.ubuntu.com/ubuntu bionic/universe amd64 proftpd-basic amd64 1.3.5e-1build1 [2015 kB]Unpacking libmagickwand-6.q16-3:amd64 (8:6.9.7.4+dfsg-16ubuntu6.4) ...Setting up libllvm6.0:amd64 (1:6.0-1ubuntu2) ...Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 libmemcached11 amd64 1.0.18-4.2 [83.3 kB] Applying admin.0002_logentry_remove_auto_add... OKPreparing to unpack .../libmemcached11_1.0.18-4.2_amd64.deb ...Setting up libwebpdemux2:amd64 (0.6.1-2) ...2.py3-none-any.whl (58kB)Get:75 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libwavpack1 amd64 5.1.0-2ubuntu1.2 [76.5 kB] 73% [10 Sources store 0 B] [18 Packages 7883 kB/8570 kB 92%] 35% |███████████▍ | 706kB 5.2MB/s eta 0:00:01 Preparing to unpack .../45-python-pip-whl_9.0.1-2.3~ubuntu1_all.deb ...Selecting previously unselected package imagemagick-6-common.90% [18 Packages store 0 B] Setting up libmp3lame0:amd64 (3.100-2) ...94% [18 Packages store 0 B] Get:19 http://archive.ubuntu.com/ubuntu bionic/universe Translation-en [4941 kB]Preparing to unpack .../128-mesa-vdpau-drivers_18.0.5-0ubuntu0~18.04.1_amd64.deb ... 72% |███████████████████████▎ | 727kB 6.0MB/s eta 0:00:01 Setting up proftpd-basic (1.3.5e-1build1) ...Receiving objects: 29% (1616/5570), 2.15 MiB | 2.14 MiB/s Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/js/prettify-min.js' 63% |████████████████████▍ | 5.2MB 6.0MB/s eta 0:00:01 er-2.0.0-py3-none-any.whl (69kB)Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/cancel.js'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/sv.js'Selecting previously unselected package gcc-7.90% [45 manpages-dev 4059 B/2217 kB 0%] 4611 kB/s 1s89% [43 libpython3.6-dev 43.9 MB/44.8 MB 98%] 4611 kB/s 1s 100% |████████████████████████████████| 512kB 1.7MB/s 99% |████████████████████████████████| 542kB 6.7MB/s eta 0:00:01 Copying '/home/paperless/paperless/src/documents/static/documents/img/png.png' Running setup.py bdist_wheel for inotify-simple ... - 82% |██████████████████████████▎ | 2.2MB 5.9MB/s eta 0:00:01 14% |████▊ | 112kB 6.4MB/s eta 0:00:01 r-0.9.1.tar.gz14% [29 libgs9-common 2611 B/5094 kB 0%] libxcb-xfixes0 libxfixes3 libxrender1 libxshmfence1 libxvidcore4 libzvbi-common libzvbi0 mesa-va-drivers mesa-vdpau-driversupdate-alternatives: using /usr/bin/display-im6.q16 to provide /usr/bin/display (display) in auto mode Running setup.py bdist_wheel for langdetect ... |Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/css/default.css'Unpacking libxfixes3:amd64 (1:5.0.3-1) ...91% [Waiting for headers] 4630 kB/s 1s 75% |████████████████████████▏ | 409kB 5.2MB/s eta 0:00:01 15% [11 cpp-7 5431 kB/6738 kB 81%]Preparing to unpack .../081-libzvbi0_0.2.35-13_amd64.deb ... 100% |████████████████████████████████| 71kB 3.6MB/s Selecting previously unselected package libzvbi0:amd64.Selecting previously unselected package libcairo2:amd64.Unpacking libthai-data (0.1.27-2) ...72% [105 libllvm6.0 11.5 MB/14.5 MB 79%] 3755 kB/s 4s 18% |█████▉ | 153kB 5.2MB/s eta 0:00:01 94% [18 Packages store 0 B] [28 Packages 1595 B/711 kB 0%] Preparing to unpack .../137-unpaper_6.1-2_amd64.deb ...Last login: Sun Jan 20 19:46:40 2019 from 192.168.1.136.6.tar.gzSetting up libubsan0:amd64 (7.3.0-27ubuntu1~18.04) ...Get:48 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libcrystalhd3 amd64 1:0.0~git20110715.fdd2f19-12 [45.8 kB] 93% |██████████████████████████████ | 2.9MB 5.7MB/s eta 0:00:01 -py2.py3-none-any.whl (88kB)0% [1 libapr1 2614 B/90.9 kB 3%] 60% |███████████████████▎ | 215kB 5.2MB/s eta 0:00:01 Collecting babel==2.6.0 (from -r requirements.txt (line 6))Get:9 http://archive.ubuntu.com/ubuntu bionic/main amd64 libisl19 amd64 0.19-1 [551 kB] | fonts-ipafont-gothic fonts-arphic-ukai fonts-arphic-uming fonts-nanum python-pil-doc python3-pil-dbg libvdpau-va-gl1Setting up cpp (4:7.3.0-3ubuntu2.1) ...Get:51 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libopenjp2-7 amd64 2.3.0-1 [145 kB]Selecting previously unselected package libmemcachedutil2:amd64. Running setup.py bdist_wheel for regex ... /Get:119 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libtesseract4 amd64 4.00~git2288-10f4998a-2 [1163 kB] 79% [Waiting for headers] 4630 kB/s 2sSelecting previously unselected package libaprutil1-dbd-sqlite3:amd64. 85% |███████████████████████████▌ | 307kB 5.9MB/s eta 0:00:01 Selecting previously unselected package libavahi-common-data:amd64.Get:44 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpython3-dev amd64 3.6.7-1~18.04 [7328 B] Selecting previously unselected package libjbig0:amd64. 27% |████████▊ | 2.2MB 5.2MB/s eta 0:00:02 Selecting previously unselected package libxcb-dri2-0:amd64. Applying reminders.0002_auto_20181007_1420... OK36% [Working] Get:30 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libgs9 amd64 9.26~dfsg+0-0ubuntu0.18.04.3 [2263 kB]Unpacking libdjvulibre21:amd64 (3.5.27.1-8) ...34% [Waiting for headers] 65% |█████████████████████ | 5.3MB 5.9MB/s eta 0:00:01 libmagickwand-6.q16-3 libmp3lame0 libmpg123-0 libnetpbm10 libnspr4 libnss3 libogg0 libopenexr22 libopenjp2-7 libopenmpt0Selecting previously unselected package python3-pil:amd64. 22% |███████▎ | 706kB 5.7MB/s eta 0:00:01 25% [12 Translation-en store 0 B] [10 Sources 1717 kB/9051 kB 19%] [Waiting for headers] Running setup.py bdist_wheel for pdftotext ... doneUnpacking libdrm-intel1:amd64 (2.4.91-2) ...Preparing to unpack .../06-libc6-dev_2.27-3ubuntu1_amd64.deb ...Enabling module setenvif.91% [18 Packages store 0 B] 56% [102 libgif7 2615 B/30.6 kB 9%] 3755 kB/s 8sUnpacking libwebpmux3:amd64 (0.6.1-2) ...Receiving objects: 27% (1504/5570), 2.15 MiB | 2.14 MiB/s Not uninstalling idna at /usr/lib/python3/dist-packages, outside environment /usrUnpacking liblept5 (1.75.3-3) ... Stored in directory: /root/.cache/pip/wheels/97/3e/62/04d426143d73ee23cb6bc1cabc52563c452889a43f71d32338Unpacking build-essential (12.4ubuntu1) ...Get:49 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libgsm1 amd64 1.0.13-4build1 [22.4 kB]31% [24 gcc-7 7325 kB/7455 kB 98%]13% [Waiting for headers] Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.16.133|:443... Running setup.py bdist_wheel for python-levenshtein ... |97% [18 Packages store 0 B] 99% [Waiting for headers] 4944 kB/s 0s 22% |███████▏ | 604kB 6.0MB/s eta 0:00:01 0% [Working] Receiving objects: 24% (1337/5570), 2.15 MiB | 2.14 MiB/s 33% [Waiting for headers] 4081 kB/s 14s 89% |████████████████████████████▌ | 6.3MB 6.0MB/s eta 0:00:01 Setting up libgdk-pixbuf2.0-bin (2.36.11-2) ... 86% |███████████████████████████▋ | 6.1MB 6.0MB/s eta 0:00:01 Selecting previously unselected package libsoxr0:amd64.Preparing to unpack .../000-fonts-dejavu-core_2.37-1_all.deb ...Collecting pycodestyle==2.4.0 (from -r requirements.txt (line 50))Preparing to unpack .../26-g++-7_7.3.0-27ubuntu1~18.04_amd64.deb ... 31% |██████████▎ | 614kB 6.0MB/s eta 0:00:01 Setting up libdjvulibre-text (3.5.27.1-8) ...Processing triggers for systemd (237-3ubuntu10.11) ...Get:49 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 python3-dev amd64 3.6.7-1~18.04 [1288 B] Selecting previously unselected package python3-keyring. Downloading https://files.pythonhosted.org/packages/a2/12/ced7105d2de62fa7c8fb5fce92cc4ce66b57c95fb875e9318dba7f8c5db0/toml-0.10.0Preparing to unpack .../073-libvpx5_1.7.0-3_amd64.deb ...Building wheels for collected packages: backcall, docopt, filemagic, inotify-simple, langdetect, pdftotext, pyocr, pytest-env, pytes7% [Waiting for headers] Unpacking libssh-gcrypt-4:amd64 (0.8.0~20170825.94fa1e38-1ubuntu0.2) ...Unpacking gsfonts (1:8.11+urwcyr1.0.7~pre44-4.4) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/tr.js'Need to get 64.4 MB of archives.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/calendar-icons.svg'Copying '/home/paperless/paperless/src/paperless/static/paperless/img/favicon.ico'Enabling module authn_file. 38% |████████████▍ | 2.8MB 5.9MB/s eta 0:00:01 Preparing to unpack .../15-libasan4_7.3.0-27ubuntu1~18.04_amd64.deb ...Get:27 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 g++-7 amd64 7.3.0-27ubuntu1~18.04 [7570 kB] 33% |██████████▊ | 901kB 5.2MB/s eta 0:00:01 Collecting py==1.7.0 (from -r requirements.txt (line 49))20% [Waiting for headers] 99% |████████████████████████████████| 921kB 6.0MB/s eta 0:00:01 Selecting previously unselected package proftpd-basic.Selecting previously unselected package imagemagick. 4% |█▎ | 286kB 5.9MB/s eta 0:00:02 Downloading https://files.pythonhosted.org/packages/62/00/ee1d7de624db8ba7090d1226aebefab96a2c71cd5cfa7629d6ad3f61b79e/urllib3-1.2 Downloading https://files.pythonhosted.org/packages/ac/9e/1aa87c0c59f9731820bfd20a8b148d97b315530c2c92d1fb300328c8c42f/dateparser-Selecting previously unselected package make.Collecting pexpect==4.6.0 (from -r requirements.txt (line 42)) 16% |█████▎ | 512kB 5.8MB/s eta 0:00:01 31% |██████████▏ | 2.3MB 5.9MB/s eta 0:00:01 Get:32 http://archive.ubuntu.com/ubuntu bionic/main amd64 build-essential amd64 12.4ubuntu1 [4758 B] 42% [30 libdpkg-perl 2613 B/211 kB 1%] 4081 kB/s 12s9.2 filelock-3.0.10 filemagic-1.6 fuzzywuzzy-0.15.0 gunicorn-19.9.0 idna-2.7 imagesize-1.1.0 inotify-simple-1.1.8 ipython-7.1.1 ipyt2.py3-none-any.whl (83kB)Selecting previously unselected package libatomic1:amd64.Preparing to unpack .../087-libvorbisfile3_1.3.5-4.2_amd64.deb ...Selecting previously unselected package optipng. Downloading https://files.pythonhosted.org/packages/f1/ca/10332a30cb25b627192b4ea272c351bce3ca1091e541245cccbace6051d8/requests-2.Collecting traitlets==4.3.2 (from -r requirements.txt (line 76))34% [56 libthai-data 2613 B/133 kB 2%] Installing collected packages: alabaster, apipkg, atomicwrites, attrs, pytz, babel, backcall, certifi, coverage, idna, urllib3, requGet:55 http://archive.ubuntu.com/ubuntu bionic/main amd64 libgdk-pixbuf2.0-0 amd64 2.36.11-2 [165 kB]Unpacking libthai0:amd64 (0.1.27-2) ...Preparing to unpack .../133-python3-pyocr_0.3.0-1_all.deb ...Fetched 85.2 MB in 19s (4415 kB/s) libpoppler-cpp-dev libpoppler-cpp0v5 libpoppler-dev libpoppler73 librsvg2-2 librsvg2-common libsensors4 libshine3 libsnappy1v5Get:23 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse Sources [3820 B]Preparing to unpack .../099-libdrm-radeon1_2.4.91-2_amd64.deb ...Preparing to unpack .../30-dpkg-dev_1.19.0.5ubuntu2.1_all.deb ...Unpacking libalgorithm-merge-perl (0.08-3) ...0% [1 InRelease gpgv 242 kB] [3 InRelease 28.7 kB/88.7 kB 32%] 41% |█████████████▎ | 317kB 5.9MB/s eta 0:00:01 Selecting previously unselected package libnss3:amd64.Selecting previously unselected package ghostscript.Unpacking libspeex1:amd64 (1.2~rc1.2-1ubuntu2) ...Get:5 http://archive.ubuntu.com/ubuntu bionic/main Sources [829 kB]Copying '/home/paperless/paperless/src/documents/static/documents/img/pdf.png'Get:132 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-olefile all 0.45.1-1 [33.3 kB] 97% [22 Sources store 0 B] 4229 kB/s 0sSelecting previously unselected package libmemcached11:amd64.Preparing to unpack .../124-libxcb-sync1_1.13-1_amd64.deb ... libssh-gcrypt-4 libswresample2 libtesseract4 libthai-data libthai0 libtheora0 libtiff5 libtwolame0 libva-drm2 libva-x11-2 libva20 upgraded, 4 newly installed, 0 to remove and 19 not upgraded..7-py2.py3-none-any.whl 0% |▏ | 30kB 6.7MB/s eta 0:00:02 90% [Working] 4611 kB/s 1s Downloading https://files.pythonhosted.org/packages/9a/05/6bad05742d185ec2fabfa4deab05cafde286eb3f383fba24b3674340aca2/django_crisPreparing to unpack .../056-libdatrie1_0.2.10-7_amd64.deb ...Get:25 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libcupsimage2 amd64 2.2.7-1ubuntu2.3 [18.6 kB]Preparing to unpack .../070-libtwolame0_0.3.13-3_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-no.svg'Unpacking libcupsimage2:amd64 (2.2.7-1ubuntu2.3) ...10% [11 cpp-7 4059 B/6738 kB 0%] Selecting previously unselected package libwebpmux3:amd64.Preparing to unpack .../10-ssl-cert_1.0.39_all.deb ... 7% |██▌ | 204kB 5.8MB/s eta 0:00:01 libjpeg8 liblcms2-2 liblept5 libllvm6.0 liblqr-1-0 libltdl7 libmagickcore-6.q16-3 libmagickcore-6.q16-3-extra 46% |██████████████▊ | 3.7MB 5.9MB/s eta 0:00:01 Unpacking libjbig0:amd64 (2.1-3.1build1) ...Selecting previously unselected package libogg0:amd64.rvice.Selecting previously unselected package libxshmfence1:amd64. Running setup.py bdist_wheel for filemagic ... -Hit:1 http://archive.ubuntu.com/ubuntu bionic InReleasePassword (again): Get:29 http://archive.ubuntu.com/ubuntu bionic/main amd64 make amd64 4.1-9.1ubuntu1 [154 kB] Get:25 http://archive.ubuntu.com/ubuntu bionic-updates/universe Sources [122 kB]100% [Waiting for headers] 4630 kB/s 0sEnabling module reqtimeout.100% [Waiting for headers] 4944 kB/s 0s 83% |██████████████████████████▊ | 5.9MB 6.0MB/s eta 0:00:01 Selecting previously unselected package libfile-fcntllock-perl.Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/js/ajax-form.js' 97% |███████████████████████████████▎| 81kB 5.4MB/s eta 0:00:01 Selecting previously unselected package libtwolame0:amd64.Collecting factory-boy==2.11.1 (from -r requirements.txt (line 23))26% [10 Sources 1908 kB/9051 kB 21%] [13 Packages 2687 B/113 kB 2%] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/rtl.css'Preparing to unpack .../012-libltdl7_2.4.6-2_amd64.deb ...98% [27 Translation-en store 0 B] 4229 kB/s 0sSetting up libx264-152:amd64 (2:0.152.2854+gite9a5903-2) ...5% [Working] 97% |███████████████████████████████▎| 3.0MB 6.0MB/s eta 0:00:01 10% [17 libmagickwand-6.q16-3 1165 B/293 kB 0%] Preparing to unpack .../032-hicolor-icon-theme_0.17-2_all.deb ...Get:15 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 Packages [1444 B]Selecting previously unselected package libstdc++-7-dev:amd64.14% [Waiting for headers] Unpacking libfakeroot:amd64 (1.22-2ubuntu1) ...Setting up libpixman-1-0:amd64 (0.34.0-2) ... 95% |██████████████████████████████▌ | 112kB 6.4MB/s eta 0:00:01 Collecting pytest-sugar==0.9.1 (from -r requirements.txt (line 58))Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/de.js'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/core.js'Get:31 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse Translation-en [3356 B] fontconfig fontconfig-config fonts-dejavu-core fonts-droid-fallback fonts-noto-mono ghostscript gsfonts hicolor-icon-themeUnpacking cpp-7 (7.3.0-27ubuntu1~18.04) ...Get:109 http://archive.ubuntu.com/ubuntu bionic/main amd64 libnetpbm10 amd64 2:10.0-15.3build1 [58.0 kB] 81% [Working] 4630 kB/s 2s37% [Waiting for headers] 28% [10 Sources 2366 kB/9051 kB 26%] [14 Translation-en 2689 B/64.2 kB 4%] 26% |████████▍ | 1.9MB 5.8MB/s eta 0:00:01 ests, docopt, coveralls, tzlocal, regex, python-dateutil, dateparser, decorator, django-cors-headers, django-crispy-forms, django-exGet:25 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 gcc amd64 4:7.3.0-3ubuntu2.1 [5184 B] 99% |████████████████████████████████| 2.7MB 5.6MB/s eta 0:00:01 0% [5 Sources store 0 B] [3 InRelease gpgv 88.7 kB] [Waiting for headers] 3% |█▏ | 286kB 1.6MB/s eta 0:00:05 Setting up libapache2-mod-wsgi-py3 (4.5.17-1) ...Selecting previously unselected package libva2:amd64.Get:43 http://archive.ubuntu.com/ubuntu bionic/main amd64 libpixman-1-0 amd64 0.34.0-2 [229 kB]Setting up libalgorithm-merge-perl (0.08-3) ...Preparing to unpack .../031-gsfonts_1%3a8.11+urwcyr1.0.7~pre44-4.4_all.deb ...Selecting previously unselected package binutils-common:amd64.Unpacking libllvm6.0:amd64 (1:6.0-1ubuntu2) ...Get:17 http://archive.ubuntu.com/ubuntu bionic/restricted Sources [5324 B]Setting up libcrystalhd3:amd64 (1:0.0~git20110715.fdd2f19-12) ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/css/font-awesome-4.0.3.css'8.0-py2.py3-none-any.whl 56% |██████████████████▎ | 1.1MB 33.1MB/s eta 0:00:01 Unpacking librsvg2-common:amd64 (2.40.20-2) ...Setting up linux-libc-dev:amd64 (4.15.0-43.46) ...Setting up libalgorithm-diff-perl (1.19.03-1) ...Unpacking python3-lib2to3 (3.6.7-1~18.04) ...Retype new UNIX password: 11.02.tar.gz (644kB) 70% |██████████████████████▋ | 5.7MB 5.8MB/s eta 0:00:01 Setting up libmagickcore-6.q16-3-extra:amd64 (8:6.9.7.4+dfsg-16ubuntu6.4) ... 42% |█████████████▌ | 389kB 5.9MB/s eta 0:00:01 35% [Working] 92% |█████████████████████████████▋ | 706kB 5.2MB/s eta 0:00:01 2% [Waiting for headers] Unpacking poppler-data (0.4.8-2) ...Receiving objects: 11% (613/5570) 99% [Working] 4944 kB/s 0sUnpacking libxcb-dri2-0:amd64 (1.13-1) ...87% [18 Packages store 0 B] [19 Translation-en 3930 kB/4941 kB 80%]Unpacking libcilkrts5:amd64 (7.3.0-27ubuntu1~18.04) ...36% [64 librsvg2-2 2614 B/98.6 kB 3%] 94% |██████████████████████████████▏ | 942kB 6.0MB/s eta 0:00:01 To activate the new configuration, you need to run:98% [26 Packages store 0 B] 4229 kB/s 0sUnpacking libgomp1:amd64 (8.2.0-1ubuntu2~18.04) ... 40% |████████████▉ | 3.3MB 5.8MB/s eta 0:00:01 Setting up binutils-x86-64-linux-gnu (2.30-21ubuntu1~18.04) ...Preparing to unpack .../109-libnspr4_2%3a4.18-1ubuntu1_amd64.deb ...Get:2 http://security.ubuntu.com/ubuntu bionic-security InRelease [83.2 kB]Unpacking python3-keyrings.alt (3.0-1) ...Get:134 http://archive.ubuntu.com/ubuntu bionic/universe amd64 python3-pyocr all 0.3.0-1 [11.8 kB] librsvg2-bin lm-sensors speex libwmf0.2-7-gtk poppler-utils fonts-japanese-mincho | fonts-ipafont-mincho fonts-japanese-gothic 100% |████████████████████████████████| 358kB 2.0MB/s 77% |████████████████████████▉ | 5.5MB 6.0MB/s eta 0:00:01 Preparing to unpack .../040-libvdpau1_1.1.1-3ubuntu1_amd64.deb ...Selecting previously unselected package python3-dev.Setting up libdrm-amdgpu1:amd64 (2.4.91-2) ...Selecting previously unselected package dh-python. 41% |█████████████▎ | 3.0MB 5.8MB/s eta 0:00:01 100% |████████████████████████████████| 184kB 3.1MB/s Unpacking libpoppler73:amd64 (0.62.0-2ubuntu2.5) ...Get:2 http://archive.ubuntu.com/ubuntu bionic/main amd64 fontconfig-config all 2.12.6-0ubuntu2 [55.8 kB]Get:2 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libbinutils amd64 2.30-21ubuntu1~18.04 [502 kB]Preparing to unpack .../104-libllvm6.0_1%3a6.0-1ubuntu2_amd64.deb ... 1% |▎ | 81kB 2.2MB/s eta 0:00:04 Selecting previously unselected package libfontconfig1:amd64.Get:64 http://archive.ubuntu.com/ubuntu bionic/main amd64 librsvg2-2 amd64 2.40.20-2 [98.6 kB] 69% |██████████████████████▎ | 4.9MB 5.9MB/s eta 0:00:01 Enabling module alias.Selecting previously unselected package libssh-gcrypt-4:amd64.1% [2 libbinutils 2613 B/502 kB 1%] Email address: Unpacking libpangocairo-1.0-0:amd64 (1.40.14-1ubuntu0.1) ... Running setup.py bdist_wheel for python-levenshtein ... - 4% |█▍ | 112kB 6.5MB/s eta 0:00:01 bms@pingu:~$ exit 41% [Waiting for headers] 4081 kB/s 12sSelecting previously unselected package python3-setuptools.Preparing to unpack .../42-libpython3.6-dev_3.6.7-1~18.04_amd64.deb ...31% [Waiting for headers] 36% [27 g++-7 2816 kB/7570 kB 37%] 4081 kB/s 13sSelecting previously unselected package python3-keyrings.alt.Setting up libquadmath0:amd64 (8.2.0-1ubuntu2~18.04) ...Get:32 http://archive.ubuntu.com/ubuntu bionic-backports/universe Sources [2068 B]Unpacking libmemcached11:amd64 (1.0.18-4.2) ...Get:26 http://archive.ubuntu.com/ubuntu bionic/main amd64 libijs-0.35 amd64 0.35-13 [15.5 kB](Reading database ... 15%Get:13 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [113 kB] 8% |██▉ | 716kB 2.8MB/s eta 0:00:03 Selecting previously unselected package libxcb-dri3-0:amd64.Unpacking libgdk-pixbuf2.0-0:amd64 (2.36.11-2) ...0% [5 Sources store 0 B] [3 InRelease gpgv 88.7 kB] [Waiting for headers] Get:3 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 binutils-x86-64-linux-gnu amd64 2.30-21ubuntu1~18.04 [1855 kB]42% [Waiting for headers] 4081 kB/s 12s Applying documents.0015_add_insensitive_to_match... OKCopying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/docs/js/jquery.json-view.min.js' Applying documents.0019_add_consumer_user... OKPreparing to unpack .../27-g++_4%3a7.3.0-3ubuntu2.1_amd64.deb ...Set ftpupload password: * Management: https://landscape.canonical.comUnpacking mesa-va-drivers:amd64 (18.0.5-0ubuntu0~18.04.1) ...97% [136 tesseract-ocr-osd 2747 kB/2989 kB 92%] 4630 kB/s 0sSetting up python3-pip (9.0.1-2.3~ubuntu1) ... 14% |████▋ | 92kB 5.9MB/s eta 0:00:01 Get:59 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpango-1.0-0 amd64 1.40.14-1ubuntu0.1 [153 kB] Running setup.py bdist_wheel for pyocr ... - libpoppler-cpp0v5 libpoppler-dev libpoppler73 librsvg2-2 librsvg2-common libsensors4 libshine3 libsnappy1v5 libsoxr0 libspeex1 43% |█████████████▊ | 3.1MB 6.0MB/s eta 0:00:01 Setting up libbinutils:amd64 (2.30-21ubuntu1~18.04) ... 34% |███████████ | 2.8MB 5.9MB/s eta 0:00:01 26% [24 gcc-7 2540 kB/7455 kB 34%] 32% [Working] 93% [46 python-pip-whl 2611 B/1652 kB 0%] 4611 kB/s 0s 29% |█████████▌ | 798kB 5.9MB/s eta 0:00:01 Setting up libisl19:amd64 (0.19-1) ...Collecting termcolor==1.1.0 (from -r requirements.txt (line 72))Selecting previously unselected package libmagickwand-6.q16-3:amd64.(Reading database ... 28583 files and directories currently installed.) Stored in directory: /root/.cache/pip/wheels/ec/0c/a9/1647275e7ef5014e7b83ff30105180e332867d65e7617ddafe Applying reminders.0001_initial... OK Not uninstalling requests at /usr/lib/python3/dist-packages, outside environment /usrPreparing to unpack .../118-libtesseract4_4.00~git2288-10f4998a-2_amd64.deb ...5% [8 libfftw3-double3 4061 B/735 kB 1%] 40% |█████████████ | 798kB 5.8MB/s eta 0:00:01 Collecting wcwidth==0.1.7 (from -r requirements.txt (line 80)) Stored in directory: /root/.cache/pip/wheels/ff/94/8e/dccadc6bce17c41a9dbb0c7ccd44acdb9dcc0edd9efa42eaf6 Stored in directory: /root/.cache/pip/wheels/11/5d/7e/f325d21ffec71263368df56a2af6ab3c802e0e869abd4b3c03 6% |██▏ | 552kB 3.0MB/s eta 0:00:03 9% [Waiting for headers] Unpacking linux-libc-dev:amd64 (4.15.0-43.46) ... 100% |████████████████████████████████| 81kB 3.9MB/s Preparing to unpack .../44-manpages-dev_4.15-1_all.deb ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/docs/js/highlight.pack.js' Applying admin.0001_initial... OKUnpacking libvorbisfile3:amd64 (1.3.5-4.2) ...Selecting previously unselected package ssl-cert.Get:23 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libgcc-7-dev amd64 7.3.0-27ubuntu1~18.04 [2380 kB]55% [Working] 3755 kB/s 8sSetting up libvorbisenc2:amd64 (1.3.5-4.2) ... System information as of Sun Jan 20 19:49:47 GMT 2019Get:106 http://archive.ubuntu.com/ubuntu bionic/main amd64 libopenexr22 amd64 2.2.0-11.1ubuntu1 [560 kB] 16% |█████▎ | 1.2MB 5.9MB/s eta 0:00:02 Preparing to unpack .../135-tesseract-ocr-osd_4.00~git24-0e00fe6-1.2_all.deb ... 19% |██████▏ | 1.4MB 5.8MB/s eta 0:00:01 0% [1 InRelease gpgv 242 kB] [Waiting for headers] 98% [Waiting for headers] 4944 kB/s 0s Downloading https://files.pythonhosted.org/packages/71/e8/6777f6624681c8b9701a8a0a5654f3eb56919a01a78e12bf3c73f5a3c714/pyparsing-291% [18 Packages store 0 B] 3-py2.py3-none-any.whl (214kB)Copying '/home/paperless/paperless/src/paperless/static/paperless/img/logo-dark.png' Downloading https://files.pythonhosted.org/packages/67/08/4815a09603fc800209431bec5b8bd2acf2f95abdfb558a44a42507fb94da/apipkg-1.5-update-alternatives: using /usr/bin/composite-im6.q16 to provide /usr/bin/composite-im6 (composite-im6) in auto modeGet:24 http://archive.ubuntu.com/ubuntu bionic-updates/restricted Sources [2064 B]remote: Counting objects: 100% (21/21), done. Receiving objects: 8% (446/5570) Apply all migrations: admin, auth, contenttypes, documents, reminders, sessionsPreparing to unpack .../089-libssh-gcrypt-4_0.8.0~20170825.94fa1e38-1ubuntu0.2_amd64.deb ... grads graphviz hp2xx html2ps libwmf-bin mplayer povray radiance sane-utils texlive-base-bin transfig ufraw-batch xdg-utilsPreparing to unpack .../052-libcroco3_0.6.12-2_amd64.deb ... 9% |███▏ | 307kB 5.8MB/s eta 0:00:01 7% [Waiting for headers] 38% |████████████▍ | 1.2MB 5.8MB/s eta 0:00:01 28% |█████████ | 2.3MB 6.0MB/s eta 0:00:01 Setting up libfakeroot:amd64 (1.22-2ubuntu1) ...56% [104 liblept5 4061 B/929 kB 0%] 3755 kB/s 8s 42% |█████████████▌ | 419kB 5.9MB/s eta 0:00:01 91% [18 Packages store 0 B] [22 Sources 2687 B/231 kB 1%] Processing triggers for mime-support (3.60ubuntu1) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/km.js'Preparing to unpack .../41-libfile-fcntllock-perl_0.22-3build2_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-unknown-alt.svg' 62% |████████████████████▏ | 92kB 5.5MB/s eta 0:00:01 kit-2.0.7-py3-none-any.whl (338kB)Preparing to unpack .../13-libitm1_8.2.0-1ubuntu2~18.04_amd64.deb ...Note, selecting 'proftpd-basic' instead of 'proftpd'87% [129 mesa-vdpau-drivers 4059 B/1902 kB 0%] 4630 kB/s 2sbms@pingu:~$ lxc launch ubuntu: paperless Get:90 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libssh-gcrypt-4 amd64 0.8.0~20170825.94fa1e38-1ubuntu0.2 [171 kB]Selecting previously unselected package libpaper1:amd64.Collecting pillow==5.3.0 (from -r requirements.txt (line 44)) Downloading https://files.pythonhosted.org/packages/24/3d/977140bd94bfb160f98a5c02fdfbb72325130f12a325cf993182956e9d0e/python_doteSelecting previously unselected package liblcms2-2:amd64. 47% |███████████████▏ | 3.8MB 5.8MB/s eta 0:00:01 Preparing to unpack .../48-python3-dev_3.6.7-1~18.04_amd64.deb ... 30% |█████████▋ | 194kB 5.9MB/s eta 0:00:01 61% |███████████████████▋ | 4.4MB 5.9MB/s eta 0:00:01 Get:127 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxshmfence1 amd64 1.3-1 [5028 B] Applying auth.0006_require_contenttypes_0002... OK 4% |█▍ | 358kB 2.9MB/s eta 0:00:03 Setting up libva-drm2:amd64 (2.1.0-3) ...Building dependency tree 0 updates are security updates. 54% |█████████████████▌ | 419kB 5.8MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/pt-BR.js'Selecting previously unselected package libopus0:amd64.Preparing to unpack .../063-librsvg2-2_2.40.20-2_amd64.deb ... 49% |███████████████▉ | 1.3MB 5.8MB/s eta 0:00:01 Selecting previously unselected package libgif7:amd64. Downloading https://files.pythonhosted.org/packages/37/54/2d169a102a3727f3ebe535da9263babb88a5862516ae9a798a7e458399a6/pyocr-0.5.3Get:33 http://archive.ubuntu.com/ubuntu bionic-backports/universe amd64 Packages [3472 B]remote: Enumerating objects: 21, done. Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/fonts/Roboto-Bold-webfont.woff'Unpacking libgif7:amd64 (5.1.4-2) ... 35% |███████████▎ | 2.9MB 5.9MB/s eta 0:00:01 99% |████████████████████████████████| 7.1MB 39.8MB/s eta 0:00:01 5% |█▉ | 112kB 6.5MB/s eta 0:00:01 Collecting python-dateutil==2.7.5 (from -r requirements.txt (line 61))Preparing to unpack .../33-python3-distutils_3.6.7-1~18.04_all.deb ... Applying documents.0007_auto_20160126_2114... OKUnpacking libc6-dev:amd64 (2.27-3ubuntu1) ...Get:70 http://archive.ubuntu.com/ubuntu bionic/main amd64 libtheora0 amd64 1.1.1+dfsg.1-14 [170 kB] 2% |▊ | 174kB 771kB/s eta 0:00:11 Selecting previously unselected package gsfonts.19% [Waiting for headers] Unpacking libopenjp2-7:amd64 (2.3.0-1) ...29% [Waiting for headers] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/prepopulate.min.js'Setting up apache2-utils (2.4.29-1ubuntu4.5) ...Selecting previously unselected package libcrystalhd3:amd64. 99% |████████████████████████████████| 8.1MB 6.0MB/s eta 0:00:01 Running setup.py bdist_wheel for filemagic ... doneGet:30 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse amd64 Packages [6376 B] 60% |███████████████████▍ | 1.2MB 5.1MB/s eta 0:00:01 Get:16 http://security.ubuntu.com/ubuntu bionic-security/multiverse Translation-en [996 B] 100% |████████████████████████████████| 92kB 3.8MB/s 96% |██████████████████████████████▉ | 890kB 5.2MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-unknown.svg'Selecting previously unselected package librsvg2-common:amd64.Collecting idna==2.7 (from -r requirements.txt (line 29)) 100% |████████████████████████████████| 71kB 4.2MB/s .3.0-py2.py3-none-any.whlSetting up libogg0:amd64 (1.3.2-1) ... 37% |████████████ | 317kB 6.7MB/s eta 0:00:01 Unpacking libwmf0.2-7:amd64 (0.2.8.4-12) ...Get:87 http://archive.ubuntu.com/ubuntu bionic/main amd64 libmpg123-0 amd64 1.25.10-1 [125 kB] Unpacking binutils-common:amd64 (2.30-21ubuntu1~18.04) ...Starting paperlessUnpacking libavformat57:amd64 (7:3.4.4-0ubuntu0.18.04.1) ...Setting up libva2:amd64 (2.1.0-3) ...Selecting previously unselected package libdrm-nouveau2:amd64.Collecting django-crispy-forms==1.7.2 (from -r requirements.txt (line 15))Selecting previously unselected package libvdpau1:amd64. 53% |█████████████████▎ | 3.8MB 6.0MB/s eta 0:00:01 .3.2-py2.py3-none-any.whl (74kB)Setting up binutils (2.30-21ubuntu1~18.04) ...31% [43 libpixman-1-0 2613 B/229 kB 1%] Downloading https://files.pythonhosted.org/packages/35/e0/e9e83b244eaa382ba21896dda6172617e47aff0be225eb72782cca105d3c/Sphinx-1.8.Get:39 http://archive.ubuntu.com/ubuntu bionic/main amd64 libalgorithm-diff-xs-perl amd64 0.04-5 [11.1 kB] 33% [27 g++-7 2611 B/7570 kB 0%] 4081 kB/s 14s0-py2.py3-none-any.whlPreparing to unpack .../022-libavahi-client3_0.7-3.1ubuntu1.1_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-changelink.svg'Selecting previously unselected package libpciaccess0:amd64.35% [Waiting for headers] Collecting parso==0.3.1 (from -r requirements.txt (line 40))Unpacking libaprutil1-ldap:amd64 (1.6.1-2) ...Preparing to unpack .../56-python3-wheel_0.30.0-0.2_all.deb ... Applying documents.0014_document_checksum... OKGet:69 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libswresample2 amd64 7:3.4.4-0ubuntu0.18.04.1 [55.2 kB].3.0-py2.py3-none-any.whl (59kB)Enter new UNIX password: Setting up apache2-bin (2.4.29-1ubuntu4.5) ... libxcb-sync1 libxcb-xfixes0 libxfixes3 libxrender1 libxshmfence1 libxvidcore4 libzvbi-common libzvbi0 mesa-va-driversSetting up libc6-dev:amd64 (2.27-3ubuntu1) ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/css/prettify.css' 79% |█████████████████████████▎ | 6.4MB 5.8MB/s eta 0:00:01 90% |█████████████████████████████ | 307kB 5.8MB/s eta 0:00:01 10% [Waiting for headers] 92% |█████████████████████████████▌ | 71kB 5.9MB/s eta 0:00:01 .1.1.tar.gz (112kB)Unpacking libswresample2:amd64 (7:3.4.4-0ubuntu0.18.04.1) ...36% [Waiting for headers] Applying documents.0001_initial... OK 35% |███████████▌ | 194kB 5.9MB/s eta 0:00:01 Unpacking gcc-7-base:amd64 (7.3.0-27ubuntu1~18.04) ... 29% |█████████▍ | 2.4MB 5.0MB/s eta 0:00:02 Selecting previously unselected package libvpx5:amd64.Collecting langdetect==1.0.7 (from -r requirements.txt (line 36))Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/pt.js'Get:45 http://archive.ubuntu.com/ubuntu bionic/main amd64 manpages-dev all 4.15-1 [2217 kB] Unpacking libavutil55:amd64 (7:3.4.4-0ubuntu0.18.04.1) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/is.js'Get:22 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libquadmath0 amd64 8.2.0-1ubuntu2~18.04 [133 kB]Setting up libvpx5:amd64 (1.7.0-3) ...Receiving objects: 22% (1226/5570), 676.01 KiB | 1.30 MiB/s Setting up libitm1:amd64 (8.2.0-1ubuntu2~18.04) ...84% [43 libpython3.6-dev 38.4 MB/44.8 MB 86%] 4611 kB/s 2s18% [16 libasan4 2613 B/358 kB 1%] Setting up libstdc++-7-dev:amd64 (7.3.0-27ubuntu1~18.04) ...Get:108 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libmagickcore-6.q16-3-extra amd64 8:6.9.7.4+dfsg-16ubuntu6.4 [62.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/tooltag-arrowright.svg'95% [Waiting for headers] 4611 kB/s 0sGet:57 http://archive.ubuntu.com/ubuntu bionic/main amd64 libdatrie1 amd64 0.2.10-7 [17.8 kB]Get:115 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpoppler-dev amd64 0.62.0-2ubuntu2.5 [4616 B] Unpacking libfftw3-double3:amd64 (3.3.7-1) ...Adding user `ftpupload' ...Setting up libnetpbm10 (2:10.0-15.3build1) ...ode-1.2-py2.py3-none-any.whl (77kB)Preparing to unpack .../34-dh-python_3.20180325ubuntu2_all.deb ...Setting up python3-setuptools (39.0.1-2) ...Setting up libcilkrts5:amd64 (7.3.0-27ubuntu1~18.04) ...psycopg/docs/install.html#binary-install-from-pypi>.Selecting previously unselected package libwebpdemux2:amd64.(Reading database ... 35% 17% |█████▊ | 1.3MB 6.0MB/s eta 0:00:01 Setting up libgsm1:amd64 (1.0.13-4build1) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/calendar.js'Get:33 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 python3-lib2to3 all 3.6.7-1~18.04 [76.5 kB] i965-va-driver imagemagick imagemagick-6-common imagemagick-6.q16 libaacs0 libavahi-client3 libavahi-common-data 58% |██████████████████▊ | 4.2MB 5.8MB/s eta 0:00:01 1% |▍ | 81kB 5.1MB/s eta 0:00:02 t-sugar, regex, termcolor, tzlocal, python-levenshteinGet:28 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 g++ amd64 4:7.3.0-3ubuntu2.1 [1572 B] 6% [Waiting for headers] 12% |████ | 1.0MB 3.5MB/s eta 0:00:03 Downloading https://files.pythonhosted.org/packages/74/68/d87d9b36af36f44254a8d512cbfc48369103a3b9e474be9bdfe536abfc45/python_date 45% |██████████████▋ | 3.3MB 5.9MB/s eta 0:00:01 81% [43 libpython3.6-dev 35.6 MB/44.8 MB 79%] 4611 kB/s 3s0.7.0-py2.py3-none-any.whl (357kB)Selecting previously unselected package libwmf0.2-7:amd64.Get:4 http://archive.ubuntu.com/ubuntu bionic/main amd64 libaprutil1-ldap amd64 1.6.1-2 [8764 B] 97% |███████████████████████████████ | 2.6MB 5.9MB/s eta 0:00:01 Setting up cpp-7 (7.3.0-27ubuntu1~18.04) ... 100% |████████████████████████████████| 3.1MB 338kB/s 12% [Working] Downloading https://files.pythonhosted.org/packages/fa/bc/9bd3b5c2b4774d5f33b2d544f1460be9df7df2fe42f352135381c347c69a/ipython_genCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/autocomplete.js'Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/js/csrf.js'Unpacking libpython3-dev:amd64 (3.6.7-1~18.04) ...30% [Waiting for headers] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/SelectBox.js'Setting up libxcb-dri3-0:amd64 (1.13-1) ...Unpacking cpp (4:7.3.0-3ubuntu2.1) ... 59% |███████████████████ | 4.2MB 6.0MB/s eta 0:00:01 Get:6 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 apache2-bin amd64 2.4.29-1ubuntu4.5 [1071 kB]0% [1 libmemcached11 2614 B/83.3 kB 3%] 40% [Waiting for headers] 3755 kB/s 10s Get:16 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libasan4 amd64 7.3.0-27ubuntu1~18.04 [358 kB]Collecting attrs==18.2.0 (from -r requirements.txt (line 5))Preparing to unpack .../068-libswresample2_7%3a3.4.4-0ubuntu0.18.04.1_amd64.deb ... Running setup.py bdist_wheel for pdftotext ... -77% [110 libnspr4 1165 B/112 kB 1%] 3755 kB/s 3s61% [43 libpython3.6-dev 14.5 MB/44.8 MB 32%] 4081 kB/s 8s 21% |██████▊ | 194kB 6.0MB/s eta 0:00:01 Running setup.py bdist_wheel for python-levenshtein ... /Unpacking hicolor-icon-theme (0.17-2) ... 95% |██████████████████████████████▊ | 194kB 5.9MB/s eta 0:00:01 37% |████████████ | 3.1MB 5.9MB/s eta 0:00:01 Preparing to unpack .../139-va-driver-all_2.1.0-3_amd64.deb ... Downloading https://files.pythonhosted.org/packages/55/80/4bbd33f6d6b305c509a90b37c1cf7255000344f513b36827ec2c17af5ad5/inotify_simupdate-alternatives: using /usr/bin/montage-im6.q16 to provide /usr/bin/montage-im6 (montage-im6) in auto modeSetting up dpkg-dev (1.19.0.5ubuntu2.1) ...3% [Waiting for headers] Found existing installation: Pillow 5.1.0Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/tooltag-add.svg'Selecting previously unselected package fontconfig-config.Setting up libmpg123-0:amd64 (1.25.10-1) ...Preparing to unpack .../134-tesseract-ocr-eng_4.00~git24-0e00fe6-1.2_all.deb ...0% [1 InRelease gpgv 242 kB] Unpacking imagemagick-6.q16 (8:6.9.7.4+dfsg-16ubuntu6.4) ...psycopg2, py, pycodestyle, pyocr, pytest, pytest-cov, pytest-django, pytest-env, pytest-forked, termcolor, pytest-sugar, pytest-xdisSelecting previously unselected package libfftw3-double3:amd64.Collecting python-gnupg==0.4.3 (from -r requirements.txt (line 63))Setting up libvdpau1:amd64 (1.1.1-3ubuntu1) ...Setting up python3-keyring (10.6.0-1) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/sr.js'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/forms.css'Preparing to unpack .../028-libgs9-common_9.26~dfsg+0-0ubuntu0.18.04.3_all.deb ...Setting up libvorbis0a:amd64 (1.3.5-4.2) ...Preparing to unpack .../026-libjbig2dec0_0.13-6_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ru.js'17% [Waiting for headers] Selecting previously unselected package libgdk-pixbuf2.0-0:amd64.Selecting previously unselected package libgdk-pixbuf2.0-bin.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/inline-delete.svg'Setting up libbluray2:amd64 (1:1.0.2-3) ...8% [7 libc6-dev 2563 kB/2587 kB 99%] 37% |████████████ | 1.0MB 6.0MB/s eta 0:00:01 74% |███████████████████████▉ | 2.3MB 5.8MB/s eta 0:00:01 17% |█████▌ | 1.4MB 5.1MB/s eta 0:00:02 51% |████████████████▋ | 1.6MB 5.8MB/s eta 0:00:01 Selecting previously unselected package libvorbisenc2:amd64.Unpacking python3-secretstorage (2.3.1-2) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/az.js'bms@FortBoyard:~$ ssh pingu.lan Setting up libcairo2:amd64 (1.15.10-2) ... 92% |█████████████████████████████▋ | 501kB 5.8MB/s eta 0:00:01 Preparing to unpack .../007-libfftw3-double3_3.3.7-1_amd64.deb ...))Unpacking python3-pip (9.0.1-2.3~ubuntu1) ...Reading package lists... 83%35% [Waiting for headers] Unpacking libtiff5:amd64 (4.0.9-5) ...77% [Waiting for headers] 3755 kB/s 3sPreparing to unpack .../077-libx264-152_2%3a0.152.2854+gite9a5903-2_amd64.deb ... 31% |██████████ | 112kB 6.4MB/s eta 0:00:01 Setting up libxcb-shm0:amd64 (1.13-1) ...Get:62 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpangoft2-1.0-0 amd64 1.40.14-1ubuntu0.1 [33.2 kB]Unpacking libopenexr22:amd64 (2.2.0-11.1ubuntu1) ...update-alternatives: using /usr/bin/animate-im6.q16 to provide /usr/bin/animate (animate) in auto modeSelecting previously unselected package libmagickcore-6.q16-3-extra:amd64.Setting up libopenmpt0:amd64 (0.3.6-1) ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/js/coreapi-0.1.1.js'Selecting previously unselected package libswresample2:amd64.Get:121 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libx11-xcb1 amd64 2:1.6.4-3ubuntu0.1 [9560 B] Unpacking libtsan0:amd64 (8.2.0-1ubuntu2~18.04) ...Preparing to unpack .../086-libmpg123-0_1.25.10-1_amd64.deb ...Get:57 http://archive.ubuntu.com/ubuntu bionic/universe amd64 python3-wheel all 0.30.0-0.2 [36.5 kB] 97% [18 Packages store 0 B] Running setup.py bdist_wheel for docopt ... doneCollecting gunicorn==19.9.0 (from -r requirements.txt (line 28)) Running setup.py bdist_wheel for regex ... - 22% |███████▎ | 1.8MB 5.6MB/s eta 0:00:02 41% [Working] 4081 kB/s 12sbms@FortBoyard:~$ Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/docs/css/base.css'bms@FortBoyard:~$ e bms@pingu:~$ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/bmsleight/paperless/master/scripts/lxc/lxc-install.21% [8 Sources store 0 B] [10 Sources 686 kB/9051 kB 8%] [11 Packages 134 kB/242 kB 56%] 50% [Waiting for headers] 3755 kB/s 9s 75% |████████████████████████▏ | 6.1MB 5.8MB/s eta 0:00:01 Get:140 http://archive.ubuntu.com/ubuntu bionic/universe amd64 va-driver-all amd64 2.1.0-3 [4376 B] 50% [86 libgme0 1165 B/121 kB 1%] 3755 kB/s 8s37% [Waiting for headers] 56% |██████████████████ | 1.5MB 6.0MB/s eta 0:00:01 Requirement already satisfied: setuptools>=18.5 in /usr/lib/python3/dist-packages (from ipython==7.1.1->-r requirements.txt (line 33ed-0.2-py2.py3-none-any.whl18% [Waiting for headers] Enabling conf charset.Get:31 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 dpkg-dev all 1.19.0.5ubuntu2.1 [608 kB] 36% [Waiting for headers] Retype new UNIX password: 9% [9 libisl19 2613 B/551 kB 0%] openbsd-inetd | inet-superserver proftpd-mod-ldap proftpd-mod-mysql proftpd-mod-odbc proftpd-mod-pgsql proftpd-mod-sqlitePreparing to unpack .../52-python3-pip_9.0.1-2.3~ubuntu1_all.deb ...Password (again): 0% [5 Sources store 0 B] [3 InRelease gpgv 88.7 kB] [8 Sources 2687 B/181 kB 1%] gnupg is already the newest version (2.2.4-1ubuntu1.2).Get:21 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libmpx2 amd64 8.2.0-1ubuntu2~18.04 [11.7 kB]Unpacking libgdk-pixbuf2.0-bin (2.36.11-2) ... libmemcached11 libmemcachedutil2 proftpd-basic proftpd-docSelecting previously unselected package libgme0:amd64.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/change_form.js'.0-py2.py3-none-any.whlSetting up libthai-data (0.1.27-2) ...Setting up libdrm-nouveau2:amd64 (2.4.91-2) ...Setting up imagemagick-6.q16 (8:6.9.7.4+dfsg-16ubuntu6.4) ... 55% |█████████████████▊ | 1.7MB 6.0MB/s eta 0:00:01 Get:138 http://archive.ubuntu.com/ubuntu bionic/universe amd64 unpaper amd64 6.1-2 [242 kB] Cloning into 'paperless'...Selecting previously unselected package libavformat57:amd64.Setting up libwavpack1:amd64 (5.1.0-2ubuntu1.2) ...Unpacking libnspr4:amd64 (2:4.18-1ubuntu1) ...bms@pingu:~$ # Run the install script48% [43 libpython3.6-dev 4057 B/44.8 MB 0%] 4081 kB/s 12sg-0.4.3-py2.py3-none-any.whlReceiving objects: 4% (223/5570) 20% |██████▋ | 399kB 5.9MB/s eta 0:00:01 Usage of /: 2.9% of 2.68TB IP address for br0: 192.168.1.22744% [Waiting for headers] 3755 kB/s 10sSelecting previously unselected package libc-dev-bin. 63% |████████████████████▍ | 4.5MB 6.0MB/s eta 0:00:01 Processing triggers for libgdk-pixbuf2.0-0:amd64 (2.36.11-2) ... 27% |████████▉ | 2.0MB 6.0MB/s eta 0:00:01 Preparing to unpack .../11-cpp_4%3a7.3.0-3ubuntu2.1_amd64.deb ...Preparing to unpack .../074-libwavpack1_5.1.0-2ubuntu1.2_amd64.deb ...33% [Waiting for headers] Get:5 http://archive.ubuntu.com/ubuntu bionic/main amd64 fonts-droid-fallback all 1:6.0.1r16-1.1 [1805 kB]0 upgraded, 58 newly installed, 0 to remove and 19 not upgraded.Unpacking libpixman-1-0:amd64 (0.34.0-2) ...Get:24 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libcups2 amd64 2.2.7-1ubuntu2.3 [211 kB] Applying documents.0013_auto_20160325_2111... OK Downloading https://files.pythonhosted.org/packages/ef/7a/212184e2e1e7f2e003b0b109c737f69518830d9c4e8d6cd9a33d17ec48f6/django_exte65% [105 libllvm6.0 5753 kB/14.5 MB 40%] 3755 kB/s 6sSelecting previously unselected package libshine3:amd64. Applying auth.0004_alter_user_username_opts... OK-2.11.1-py2.py3-none-any.whl51% [89 libopenmpt0 2613 B/561 kB 0%] 3755 kB/s 8sUnpacking netpbm (2:10.0-15.3build1) ...Collecting pytest-xdist==1.24.0 (from -r requirements.txt (line 59))Get:4 http://archive.ubuntu.com/ubuntu bionic/main amd64 fontconfig amd64 2.12.6-0ubuntu2 [169 kB]Unpacking libtwolame0:amd64 (0.3.13-3) ... 86% |███████████████████████████▊ | 51kB 5.5MB/s eta 0:00:01 Selecting previously unselected package gcc-7-base:amd64.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/widgets.css'Setting up g++-7 (7.3.0-27ubuntu1~18.04) ... 100% |████████████████████████████████| 8.1MB 130kB/s 49% [10 Sources store 0 B] [Waiting for headers] 55% |█████████████████▊ | 1.1MB 6.0MB/s eta 0:00:01 13% [Waiting for headers] Unpacking libavahi-common-data:amd64 (0.7-3.1ubuntu1.1) ... Running setup.py bdist_wheel for inotify-simple ... done9% [Waiting for headers] 33% |██████████▋ | 112kB 6.4MB/s eta 0:00:01 Unpacking libcairo2:amd64 (1.15.10-2) ... 62% |████████████████████ | 4.5MB 6.0MB/s eta 0:00:01 100% |████████████████████████████████| 931kB 1.0MB/s 71% |███████████████████████ | 5.8MB 5.9MB/s eta 0:00:01 Get:56 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 python3-venv amd64 3.6.7-1~18.04 [1208 B] 53% |█████████████████▏ | 409kB 5.2MB/s eta 0:00:01 Setting up dh-python (3.20180325ubuntu2) ... 15% |█████▏ | 307kB 5.9MB/s eta 0:00:01 Unpacking libgs9-common (9.26~dfsg+0-0ubuntu0.18.04.3) ... 44% |██████████████▍ | 1.4MB 5.9MB/s eta 0:00:01 Running setup.py bdist_wheel for regex ... \ Applying contenttypes.0002_remove_content_type_name... OKUnpacking python3-olefile (0.45.1-1) ...Copying '/usr/local/lib/python3.6/dist-packages/django_extensions/static/django_extensions/js/jquery.autocomplete.js'56% [103 libilmbase12 2614 B/71.4 kB 4%] 3755 kB/s 8sCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/lv.js'Unpacking libapr1:amd64 (1.6.3-2) ... 21% |██████▉ | 1.7MB 4.1MB/s eta 0:00:02 90% |████████████████████████████▉ | 7.3MB 5.9MB/s eta 0:00:01 Get:61 http://archive.ubuntu.com/ubuntu bionic/main amd64 libharfbuzz0b amd64 1.7.2-1ubuntu1 [232 kB] 100% |████████████████████████████████| 51kB 3.4MB/s Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/mk.js'Superuser created successfully.28% [Working] apache2 apache2-bin apache2-data apache2-utils libapache2-mod-wsgi-py3 libapr1 libaprutil1 libaprutil1-dbd-sqlite3Fetched 26.6 MB in 8s (3350 kB/s) 13% [Waiting for headers] tensions, django, django-filter, djangorestframework, docutils, execnet, text-unidecode, faker, factory-boy, filelock, filemagic, pyGet:41 http://archive.ubuntu.com/ubuntu bionic/main amd64 libvdpau1 amd64 1.1.1-3ubuntu1 [25.5 kB] 45% |██████████████▋ | 1.2MB 6.0MB/s eta 0:00:01 Setting up va-driver-all:amd64 (2.1.0-3) ...94% [136 tesseract-ocr-osd 2611 B/2989 kB 0%] 4630 kB/s 0sUnpacking libpaper-utils (1.1.24+nmu5ubuntu1) ...Preparing to unpack .../04-libc-dev-bin_2.27-3ubuntu1_amd64.deb ...Get:58 http://archive.ubuntu.com/ubuntu bionic/main amd64 libthai0 amd64 0.1.27-2 [18.0 kB]Get:136 http://archive.ubuntu.com/ubuntu bionic/universe amd64 tesseract-ocr-osd all 4.00~git24-0e00fe6-1.2 [2989 kB] Preparing to unpack .../060-libharfbuzz0b_1.7.2-1ubuntu1_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/js/bootstrap.min.js'Preconfiguring packages ...14-py3-none-any.whl (543kB)Enabling module authz_user.41% [79 libx265-146 2612 B/1026 kB 0%] 3755 kB/s 10supdate-alternatives: using /usr/bin/compare-im6.q16 to provide /usr/bin/compare (compare) in auto mode86% [43 libpython3.6-dev 41.1 MB/44.8 MB 92%] 4611 kB/s 1sGet:48 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 python3.6-dev amd64 3.6.7-1~18.04 [508 kB] 79% [113 libpoppler73 2613 B/800 kB 0%] 4630 kB/s 2sUnpacking libxshmfence1:amd64 (1.3-1) ...61% [105 libllvm6.0 2877 kB/14.5 MB 20%] 3755 kB/s 7s 29% |█████████▍ | 911kB 5.2MB/s eta 0:00:01 35% |███████████▎ | 1.1MB 6.0MB/s eta 0:00:01 Collecting dateparser==0.7.0 (from -r requirements.txt (line 12))Requirement already satisfied: chardet==3.0.4 in /usr/lib/python3/dist-packages (from -r requirements.txt (line 9))Enabling module wsgi.sh && /bin/bash lxc-install.sh"Preparing to unpack .../025-libijs-0.35_0.35-13_amd64.deb ...Get:2 http://archive.ubuntu.com/ubuntu bionic/main amd64 libmemcachedutil2 amd64 1.0.18-4.2 [9528 B]Unpacking libmagickcore-6.q16-3:amd64 (8:6.9.7.4+dfsg-16ubuntu6.4) ...Reading package lists... 0%ols-4.3.0-py3-none-any.whl (48kB) 90% |████████████████████████████▉ | 6.4MB 5.9MB/s eta 0:00:01 bms@pingu:~$ exitGet:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 libapr1 amd64 1.6.3-2 [90.9 kB]Setting up libfontconfig1:amd64 (2.12.6-0ubuntu2) ...Selecting previously unselected package proftpd-doc.94% [46 python-pip-whl 1587 kB/1652 kB 96%] 4611 kB/s 0sCollecting imagesize==1.1.0 (from -r requirements.txt (line 30))Enabling conf localized-error-pages.Selecting previously unselected package libgdk-pixbuf2.0-common.Selecting previously unselected package tesseract-ocr-osd.Setting up libilmbase12:amd64 (2.2.0-11ubuntu2) ...Receiving objects: 23% (1288/5570), 2.15 MiB | 2.14 MiB/s Preparing to unpack .../034-imagemagick_8%3a6.9.7.4+dfsg-16ubuntu6.4_amd64.deb ...Preparing to unpack .../114-libpoppler-dev_0.62.0-2ubuntu2.5_amd64.deb ...Selecting previously unselected package libx11-xcb1:amd64.Resolving deltas: 100% (3560/3560), done.Preparing to unpack .../029-libgs9_9.26~dfsg+0-0ubuntu0.18.04.3_amd64.deb ...Selecting previously unselected package tesseract-ocr-eng.0% [5 Sources store 0 B] [4 InRelease gpgv 74.6 kB] [10 Sources 126 kB/9051 kB 1%] [11 Packages 1239 B/242 kB 1%] Enter new UNIX password: Receiving objects: 64% (3565/5570), 4.67 MiB | 3.10 MiB/s 38% [Working] 3755 kB/s 11sCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/vendor/select2/select2.min.css'Setting up libva-x11-2:amd64 (2.1.0-3) ...Preparing to unpack .../101-libgif7_5.1.4-2_amd64.deb ...Selecting previously unselected package libfakeroot:amd64.84% [128 mesa-va-drivers 2611 B/1778 kB 0%] 4630 kB/s 2s Downloading https://files.pythonhosted.org/packages/fc/b6/aef66b4c52a6ad6ac18cf6ebc5731ed06d8c9ae4d3b2d9951f261150be67/imagesize-1Preparing to unpack .../55-python3-venv_3.6.7-1~18.04_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/urlify.js'Preparing to unpack .../12-libcc1-0_8.2.0-1ubuntu2~18.04_amd64.deb ...Setting up g++ (4:7.3.0-3ubuntu2.1) ...Copying '/usr/local/lib/python3.6/dist-packages/django_extensions/static/django_extensions/img/indicator.gif'Length: 3054 (3.0K) [text/plain]21% [Waiting for headers] Setting up libpango-1.0-0:amd64 (1.40.14-1ubuntu0.1) ...Unpacking libmpg123-0:amd64 (1.25.10-1) ... - Reduce system reboots and improve kernel security. Activate at: Downloading https://files.pythonhosted.org/packages/f9/76/3343e69a2a1602052f587898934e5fea395d22310d39c07955596597227c/execnet-1.5Collecting django==2.0.9 (from -r requirements.txt (line 18))Enabling module negotiation.1% [Working] Preparing to unpack .../20-libmpx2_8.2.0-1ubuntu2~18.04_amd64.deb ...Setting up libalgorithm-diff-xs-perl (0.04-5) ...1% [Waiting for headers] Unpacking libvdpau1:amd64 (1.1.1-3ubuntu1) ...Selecting previously unselected package libc6-dev:amd64.Requirement already satisfied: six==1.11.0 in /usr/lib/python3/dist-packages (from -r requirements.txt (line 68))Setting up python3.6-venv (3.6.7-1~18.04) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/nl.js'Preparing to unpack .../041-libavutil55_7%3a3.4.4-0ubuntu0.18.04.1_amd64.deb ...ramework-3.9.0-py2.py3-none-any.whl (924kB)Adding system user `proftpd' (UID 111) ...Get:2 http://archive.ubuntu.com/ubuntu bionic/main amd64 libaprutil1 amd64 1.6.1-2 [84.4 kB]41% [78 libx264-152 2613 B/609 kB 0%] 3755 kB/s 10sGet:98 http://archive.ubuntu.com/ubuntu bionic/main amd64 libdrm-intel1 amd64 2.4.91-2 [59.8 kB] Unpacking libnetpbm10 (2:10.0-15.3build1) ...Selecting previously unselected package libharfbuzz0b:amd64.Collecting toml==0.10.0 (from -r requirements.txt (line 74))Preparing to unpack .../23-gcc-7_7.3.0-27ubuntu1~18.04_amd64.deb ... 100% |████████████████████████████████| 51kB 3.2MB/s 0% [2 InRelease gpgv 83.2 kB] [5 Sources 2687 B/829 kB 0%] Unpacking libexpat1-dev:amd64 (2.2.5-3) ...Enabling site 000-default.Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/css/bootstrap.min.css'Unpacking libxcb-sync1:amd64 (1.13-1) ...Setting up fonts-dejavu-core (2.37-1) ...Unpacking proftpd-doc (1.3.5e-1build1) ... Downloading https://files.pythonhosted.org/packages/10/ad/00b090d23a222943eb0eda509720a404f531a439e803f6538f35136cae9e/alabaster-0 44% |██████████████▎ | 286kB 5.9MB/s eta 0:00:01 74% |███████████████████████▊ | 686kB 6.0MB/s eta 0:00:01 53% |█████████████████▏ | 4.3MB 5.9MB/s eta 0:00:01 Unpacking dpkg-dev (1.19.0.5ubuntu2.1) ... Downloading https://files.pythonhosted.org/packages/3d/a0/b12090c40e0b8196b973962ec71c1c541a6c04af58ba5ad85683b3de251a/coverage-4.Preparing to unpack .../098-libdrm-nouveau2_2.4.91-2_amd64.deb ...Preparing to unpack .../103-liblept5_1.75.3-3_amd64.deb ... 63% |████████████████████▎ | 112kB 6.4MB/s eta 0:00:01 Setting up libpython3.6-dev:amd64 (3.6.7-1~18.04) ... 74% |████████████████████████ | 5.3MB 5.8MB/s eta 0:00:01 Preparing to unpack .../100-libgdk-pixbuf2.0-bin_2.36.11-2_amd64.deb ... 37% |████████████ | 2.7MB 6.0MB/s eta 0:00:01 Selecting previously unselected package libasan4:amd64.Setting up libmemcached11:amd64 (1.0.18-4.2) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/responsive.css'30% [10 Sources 2699 kB/9051 kB 30%] [Waiting for headers] Adding new user `proftpd' (UID 111) with group `nogroup' ...Get:124 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxcb-present0 amd64 1.13-1 [5540 B] 40% [76 libwebp6 2613 B/185 kB 1%] 3755 kB/s 10sEnabling module dir.Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB] Selecting previously unselected package mesa-va-drivers:amd64.Need to get 85.2 MB of archives.Get:63 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpangocairo-1.0-0 amd64 1.40.14-1ubuntu0.1 [20.8 kB]Unpacking libalgorithm-diff-perl (1.19.03-1) ...0% [1 InRelease gpgv 242 kB] [3 InRelease 2602 B/88.7 kB 3%] [2 InRelease 17.1 kB/83.2 kB 21%] 30% [Working] apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.2-0 ssl-certPreparing to unpack .../062-libpangocairo-1.0-0_1.40.14-1ubuntu0.1_amd64.deb ...Setting up optipng (0.7.6-1.1) ...4.1-py2.py3-none-any.whl (118kB)Unpacking libalgorithm-diff-xs-perl (0.04-5) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/sr-Cyrl.js'update-alternatives: using /usr/bin/convert-im6.q16 to provide /usr/bin/convert (convert) in auto mode49% [10 Sources store 0 B] 96% [Working] 4944 kB/s 0sSetting up libcc1-0:amd64 (8.2.0-1ubuntu2~18.04) ... Running setup.py bdist_wheel for langdetect ... \ 77% |████████████████████████▉ | 2.4MB 6.0MB/s eta 0:00:01 Creating paperlessPreparing to unpack .../011-liblqr-1-0_0.4.2-2.1_amd64.deb ...Get:89 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libopenmpt0 amd64 0.3.6-1 [561 kB] Unpacking libcroco3:amd64 (0.6.12-2) ...75% [10 Sources store 0 B] [19 Translation-en 2685 B/4941 kB 0%] Preparing to unpack .../049-libmp3lame0_3.100-2_amd64.deb ...Setting up ghostscript (9.26~dfsg+0-0ubuntu0.18.04.3) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/da.js'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/fr.js'Setting up proftpd-doc (1.3.5e-1build1) ... 68% |█████████████████████▊ | 1.8MB 6.0MB/s eta 0:00:01 Get:91 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 libavformat57 amd64 7:3.4.4-0ubuntu0.18.04.1 [949 kB] Unpacking libopenmpt0:amd64 (0.3.6-1) ...Preparing to unpack .../001-fontconfig-config_2.12.6-0ubuntu2_all.deb ...Selecting previously unselected package libchromaprint1:amd64.Get:11 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [242 kB] Unpacking libdpkg-perl (1.19.0.5ubuntu2.1) ...Need to get 3273 kB of archives.Preparing to unpack .../039-libva-x11-2_2.1.0-3_amd64.deb ...Selecting previously unselected package libavcodec57:amd64.Preparing to unpack .../51-python3-keyrings.alt_3.0-1_all.deb ...Selecting previously unselected package libopenmpt0:amd64.ice.28% [34 imagemagick-6.q16 2613 B/423 kB 1%] Preparing to unpack .../04-liblua5.2-0_5.2.4-1.1build1_amd64.deb ...Get:46 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxrender1 amd64 1:0.9.10-1 [18.7 kB] 74% |███████████████████████▊ | 6.0MB 5.8MB/s eta 0:00:01 Setting up libssh-gcrypt-4:amd64 (0.8.0~20170825.94fa1e38-1ubuntu0.2) ...Get:7 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libgomp1 amd64 8.2.0-1ubuntu2~18.04 [76.4 kB]After this operation, 7262 kB of additional disk space will be used.Unpacking unpaper (6.1-2) ...13% [24 libcups2 2613 B/211 kB 1%] Collecting coverage==4.5.1 (from -r requirements.txt (line 10)) Applying auth.0008_alter_user_username_max_length... OKGet:55 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 python3.6-venv amd64 3.6.7-1~18.04 [6184 B] Get:34 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 imagemagick-6.q16 amd64 8:6.9.7.4+dfsg-16ubuntu6.4 [423 kB](Reading database ... 0% [3 InRelease gpgv 88.7 kB] [5 Sources 598 kB/829 kB 72%] Not uninstalling attrs at /usr/lib/python3/dist-packages, outside environment /usr 78% |█████████████████████████▏ | 2.1MB 5.8MB/s eta 0:00:01 21% [6 Sources store 0 B] [10 Sources 625 kB/9051 kB 7%] [11 Packages 119 kB/242 kB 49%] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-deletelink.svg'Setting up libaprutil1-ldap:amd64 (1.6.1-2) ... 71% |██████████████████████▉ | 2.2MB 6.0MB/s eta 0:00:01 Get:12 http://security.ubuntu.com/ubuntu bionic-security/main Translation-en [91.6 kB] 8% |██▋ | 583kB 5.9MB/s eta 0:00:02 49% |████████████████ | 419kB 5.8MB/s eta 0:00:01 5% |█▉ | 450kB 2.2MB/s eta 0:00:04 Get:31 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 ghostscript amd64 9.26~dfsg+0-0ubuntu0.18.04.3 [51.8 kB]Get:92 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libbdplus0 amd64 0.1.2-2 [46.6 kB] 76% [43 libpython3.6-dev 30.5 MB/44.8 MB 68%] 4611 kB/s 4s Downloading https://files.pythonhosted.org/packages/8a/48/a76be51647d0eb9f10e2a4511bf3ffb8cc1e6b14e9e4fab46173aa79f981/termcolor-1 Found existing installation: certifi 2018.1.18Unpacking libopus0:amd64 (1.1.2-1ubuntu1) ...sh && /bin/bash lxc-install.sh" 38% |████████████▌ | 3.2MB 5.9MB/s eta 0:00:01 Receiving objects: 32% (1783/5570), 4.67 MiB | 3.10 MiB/s Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/actions.min.js'31% [47 libcairo2 2613 B/580 kB 0%] bms@pingu:~$ lxc launch ubuntu: paperlessSelecting previously unselected package libgs9-common. Downloading https://files.pythonhosted.org/packages/1b/e2/ffb8c1b574f972cf4183b0aac8f16b57f1e3bbe876b31555b107ea3fd009/ipython-7.1Get:38 http://archive.ubuntu.com/ubuntu bionic/main amd64 libalgorithm-diff-perl all 1.19.03-1 [47.6 kB] Downloading https://files.pythonhosted.org/packages/79/b1/eace304ef66bd7d3d8b2f78cc374b73ca03bc53664d78151e9df3b3996cc/more_itertoCollecting packaging==18.0 (from -r requirements.txt (line 39))Setting up libvorbisfile3:amd64 (1.3.5-4.2) ....1.0.tar.gzCopying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/docs/css/highlight.css'Unpacking libpaper1:amd64 (1.1.24+nmu5ubuntu1) ...Collecting python-levenshtein>=0.12; extra == "speedup" (from fuzzywuzzy[speedup]==0.15.0->-r requirements.txt (line 27))Get:8 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 gcc-7-base amd64 7.3.0-27ubuntu1~18.04 [18.9 kB]34% [Waiting for headers] Get:7 http://security.ubuntu.com/ubuntu bionic-security/multiverse Sources [1336 B]The following additional packages will be installed:Password: Copying '/usr/local/lib/python3.6/dist-packages/django_extensions/static/django_extensions/css/jquery.autocomplete.css'19% [17 liblsan0 2613 B/132 kB 2%] Collecting pyocr==0.5.3 (from -r requirements.txt (line 52))Preparing to unpack .../093-libdjvulibre-text_3.5.27.1-8_all.deb ...Get:84 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libbluray2 amd64 1:1.0.2-3 [141 kB] 20% [19 libubsan0 2613 B/126 kB 2%] 36% [61 libharfbuzz0b 2613 B/232 kB 1%] 52% |████████████████▉ | 3.7MB 5.9MB/s eta 0:00:01 Selecting previously unselected package libnspr4:amd64.Unpacking ghostscript (9.26~dfsg+0-0ubuntu0.18.04.3) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/SelectFilter2.js'Selecting previously unselected package fonts-noto-mono.Setting up libgomp1:amd64 (8.2.0-1ubuntu2~18.04) ...Setting up fontconfig-config (2.12.6-0ubuntu2) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/icon-clock.svg'21% [23 libgcc-7-dev 2611 B/2380 kB 0%] Unpacking binutils (2.30-21ubuntu1~18.04) ...Unpacking imagemagick (8:6.9.7.4+dfsg-16ubuntu6.4) ...Unpacking python3-dev (3.6.7-1~18.04) ...Setting up gcc-7 (7.3.0-27ubuntu1~18.04) ... 100% |████████████████████████████████| 849kB 1.1MB/s 11% [19 poppler-data 2611 B/1479 kB 0%] 82% |██████████████████████████▌ | 6.7MB 5.9MB/s eta 0:00:01 python3-secretstorage python3-setuptools python3-wheel python3-xdg python3.6-dev python3.6-venvCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/zh-TW.js' 98% |███████████████████████████████▌| 1.9MB 6.0MB/s eta 0:00:01 Unpacking libjbig2dec0:amd64 (0.13-6) ...43% [Waiting for headers] 3755 kB/s 10s Downloading https://files.pythonhosted.org/packages/8f/67/a1aedccc143597eea90e79134d14c7364e90174d31443e14674919716d87/filemagic-187 packages can be updated.share-0.7.5 pillow-5.3.0 pluggy-0.8.0 prompt-toolkit-2.0.7 psycopg2-2.7.6.1 ptyprocess-0.6.0 py-1.7.0 pycodestyle-2.4.0 pygments-2.2Selecting previously unselected package libnetpbm10.Unpacking libcupsfilters1:amd64 (1.20.2-0ubuntu3) ... 77% |████████████████████████▉ | 6.3MB 5.9MB/s eta 0:00:01 Unpacking python3-wheel (0.30.0-0.2) ...95% [Waiting for headers] 4944 kB/s 0sGet:82 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libzvbi0 amd64 0.2.35-13 [235 kB] Setting up libxshmfence1:amd64 (1.3-1) ...Reading package lists... 46%Selecting previously unselected package libapache2-mod-wsgi-py3.98% [Working] 4630 kB/s 0s97% [21 Translation-en store 0 B] 4229 kB/s 0s5% [Waiting for headers] Setting up libpangocairo-1.0-0:amd64 (1.40.14-1ubuntu0.1) ...Setting up libxfixes3:amd64 (1:5.0.3-1) ...7.6.1-cp36-cp36m-manylinux1_x86_64.whl (2.7MB) 32% |██████████▎ | 296kB 5.6MB/s eta 0:00:01 5% [Waiting for headers] Applying documents.0004_auto_20160114_1844... OKConnection to pingu.lan closed. Downloading https://files.pythonhosted.org/packages/e5/c6/ce130213489969aa58610042dff1d908c25c731c9575af6935c2dfad03aa/pycodestyle * Canonical Livepatch is available for installation.Setting up libpython3-dev:amd64 (3.6.7-1~18.04) ... => There is 1 zombie process.Unpacking libzvbi0:amd64 (0.2.35-13) ...Selecting previously unselected package libpoppler-dev:amd64.Enabling site paperless.Get:122 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxcb-dri2-0 amd64 1.13-1 [6928 B] Setting up libtesseract4 (4.00~git2288-10f4998a-2) ...Collecting filemagic==1.6 (from -r requirements.txt (line 26)) 31% |██████████▏ | 317kB 5.9MB/s eta 0:00:01 Applying documents.0002_auto_20151226_1316... OK7% [14 libtiff5 2613 B/152 kB 2%] 14% |████▌ | 71kB 4.7MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/en.js'Get:11 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 cpp-7 amd64 7.3.0-27ubuntu1~18.04 [6738 kB]Created symlink /etc/systemd/system/multi-user.target.wants/apache-htcacheclean.service → /lib/systemd/system/apache-htcacheclean.se Downloading https://files.pythonhosted.org/packages/52/69/3c2fbdc3702358c5b34ee25e387b24838597ef099761fc9a42c166796e8f/sphinxcontr34% [55 libgdk-pixbuf2.0-0 4061 B/165 kB 2%] Setting up apache2-data (2.4.29-1ubuntu4.5) ...93% [Waiting for headers] 4611 kB/s 0sCollecting django-cors-headers==2.4.0 (from -r requirements.txt (line 14))Preparing to unpack .../05-apache2-bin_2.4.29-1ubuntu4.5_amd64.deb ...51% [Waiting for headers] 3755 kB/s 8sGet:1 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 binutils-common amd64 2.30-21ubuntu1~18.04 [193 kB]Get:7 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 apache2-utils amd64 2.4.29-1ubuntu4.5 [83.3 kB] Downloading https://files.pythonhosted.org/packages/d9/eb/6d13451769976f79c9043db562da22302a2c3d96e5d6427e8517fec9d2e5/Faker-0.9.2 99% |███████████████████████████████▊| 501kB 5.8MB/s eta 0:00:01 Unpacking binutils-x86-64-linux-gnu (2.30-21ubuntu1~18.04) ... Downloading https://files.pythonhosted.org/packages/02/ee/b6e02dc6529e82b75bb06823ff7d005b141037cb1416b10c6f00fc419dca/Pygments-2.Get:102 http://archive.ubuntu.com/ubuntu bionic/main amd64 libgif7 amd64 5.1.4-2 [30.6 kB] Unpacking python3-xdg (0.25-4ubuntu1) ...Selecting previously unselected package libavahi-common3:amd64.Selecting previously unselected package libopenexr22:amd64.Setting up libaprutil1:amd64 (1.6.1-2) ...Unpacking libdrm-amdgpu1:amd64 (2.4.91-2) ...Selecting previously unselected package libx264-152:amd64. * Support: https://ubuntu.com/advantage 10% |███▌ | 778kB 6.0MB/s eta 0:00:02 tesseract-ocr-osd unpaper va-driver-all vdpau-driver-allSetting up libopenexr22:amd64 (2.2.0-11.1ubuntu1) ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/fonts/LICENSE.txt'Selecting previously unselected package libthai0:amd64.Selecting previously unselected package fonts-dejavu-core. 26% |████████▌ | 204kB 5.9MB/s eta 0:00:01 Unpacking libquadmath0:amd64 (8.2.0-1ubuntu2~18.04) ... 100% |████████████████████████████████| 225kB 2.8MB/s Collecting snowballstemmer==1.2.1 (from -r requirements.txt (line 69))54% [95 libdjvulibre21 4061 B/559 kB 1%] 3755 kB/s 8s95% [47 python3-crypto 2613 B/244 kB 1%] 4611 kB/s 0s Applying documents.0012_auto_20160305_0040... OK https://ubuntu.com/livepatchGet:42 http://archive.ubuntu.com/ubuntu bionic/main amd64 libfile-fcntllock-perl amd64 0.22-3build2 [33.2 kB] Get:14 http://security.ubuntu.com/ubuntu bionic-security/universe Translation-en [64.2 kB]Unpacking libatomic1:amd64 (8.2.0-1ubuntu2~18.04) ... 34% |███████████ | 2.5MB 5.8MB/s eta 0:00:01 Preparing to unpack .../132-python3-pil_5.1.0-1_amd64.deb ... Downloading https://files.pythonhosted.org/packages/91/4f/f52682bfaa960445af93143df5ea0a98854f1a7829ff3e377932426bf48c/coveralls-1Get:36 http://archive.ubuntu.com/ubuntu bionic/main amd64 libfakeroot amd64 1.22-2ubuntu1 [25.9 kB] 77% [8 apache2-data 2613 B/160 kB 2%] Preparing to unpack .../072-libvorbisenc2_1.3.5-4.2_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/docs/css/jquery.json-view.min.css' Running setup.py bdist_wheel for python-levenshtein ... \68% [43 libpython3.6-dev 21.9 MB/44.8 MB 49%] 4611 kB/s 6s Running setup.py bdist_wheel for tzlocal ... \Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/pl.js'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/ms.js' 26% |████████▍ | 808kB 6.0MB/s eta 0:00:01 24% [Waiting for headers] 98% [53 python3-pip 4061 B/114 kB 4%] 4944 kB/s 0sSetting up manpages-dev (4.15-1) ... 32% |██████████▍ | 1.0MB 5.8MB/s eta 0:00:01 Copying '/home/paperless/paperless/src/documents/static/paperless.css'Preparing to unpack .../106-libwmf0.2-7_0.2.8.4-12_amd64.deb ...18% [Working] Preparing to unpack .../54-python3.6-venv_3.6.7-1~18.04_amd64.deb ... 73% |███████████████████████▌ | 5.2MB 6.0MB/s eta 0:00:01 Selecting previously unselected package libijs-0.35:amd64.Preparing to unpack .../29-libdpkg-perl_1.19.0.5ubuntu2.1_all.deb ...Setting up python3-dev (3.6.7-1~18.04) ...Unpacking fonts-droid-fallback (1:6.0.1r16-1.1) ...Collecting coveralls==1.5.1 (from -r requirements.txt (line 11))Unpacking libmemcachedutil2:amd64 (1.0.18-4.2) ...Get:67 http://archive.ubuntu.com/ubuntu bionic/main amd64 libspeex1 amd64 1.2~rc1.2-1ubuntu2 [52.1 kB]Preparing to unpack .../085-libgme0_0.6.2-1_amd64.deb ... Downloading https://files.pythonhosted.org/packages/a2/55/8f8cab2afd404cf578136ef2cc5dfb50baa1761b68c9da1fb1e4eed343c9/docopt-0.6. 44% |██████████████▏ | 3.2MB 6.0MB/s eta 0:00:01 Reading package lists... 8%Get:13 http://archive.ubuntu.com/ubuntu bionic/main amd64 libltdl7 amd64 2.4.6-2 [38.8 kB] Downloading https://files.pythonhosted.org/packages/1c/e7/017c262070af41fe251401cb0d0e1b7c38f656da634cd0c15604f1f30864/pluggy-0.8.Selecting previously unselected package libubsan0:amd64.Receiving objects: 54% (3008/5570), 4.67 MiB | 3.10 MiB/s bms@FortBoyard:~$ exit 97% |███████████████████████████████▎| 7.9MB 6.0MB/s eta 0:00:01 Preparing to unpack .../03-binutils_2.30-21ubuntu1~18.04_amd64.deb ...Get:133 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-pil amd64 5.1.0-1 [328 kB] Get:23 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libavahi-client3 amd64 0.7-3.1ubuntu1.1 [25.3 kB]Setting up mesa-vdpau-drivers:amd64 (18.0.5-0ubuntu0~18.04.1) ...1-py2.py3-none-any.whl (3.1MB)Preparing to unpack .../053-libgdk-pixbuf2.0-common_2.36.11-2_all.deb ...Get:37 http://archive.ubuntu.com/ubuntu bionic/main amd64 fakeroot amd64 1.22-2ubuntu1 [62.3 kB] 51% |████████████████▍ | 3.6MB 6.0MB/s eta 0:00:01 96% |███████████████████████████████ | 102kB 6.9MB/s eta 0:00:01 100% |████████████████████████████████| 552kB 1.5MB/s 95% |██████████████████████████████▋ | 61kB 5.2MB/s eta 0:00:01 59% |███████████████████▏ | 4.9MB 6.0MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/fonts/README.txt' Applying documents.0020_document_added... OK 100% |████████████████████████████████| 7.1MB 158kB/s 76% [105 libllvm6.0 14.4 MB/14.5 MB 99%] 3755 kB/s 4sUnpacking libwebpdemux2:amd64 (0.6.1-2) ...Unpacking libstdc++-7-dev:amd64 (7.3.0-27ubuntu1~18.04) ...Setting up libbdplus0:amd64 (0.1.2-2) ...Preparing to unpack .../055-libthai-data_0.1.27-2_all.deb ...Unpacking libx264-152:amd64 (2:0.152.2854+gite9a5903-2) ...Unpacking libaprutil1-dbd-sqlite3:amd64 (1.6.1-2) ...Selecting previously unselected package unpaper.HTTP request sent, awaiting response... 200 OKGet:135 http://archive.ubuntu.com/ubuntu bionic/universe amd64 tesseract-ocr-eng all 4.00~git24-0e00fe6-1.2 [1588 kB] Applying documents.0011_auto_20160303_1929... OKPreparing to unpack .../043-libxcb-render0_1.13-1_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/hr.js'51% [Working] 3755 kB/s 8sSetting up libxrender1:amd64 (1:0.9.10-1) ...Preparing to unpack .../094-libdjvulibre21_3.5.27.1-8_amd64.deb ...Enabling module deflate.47% [83 libavcodec57 2878 kB/4592 kB 63%] 3755 kB/s 9sReading state information... DoneUnpacking libxvidcore4:amd64 (2:1.3.5-1) ...Setting up libcupsimage2:amd64 (2.2.7-1ubuntu2.3) ... 57% |██████████████████▍ | 4.7MB 6.0MB/s eta 0:00:01 100% |████████████████████████████████| 81kB 3.5MB/s Preparing to unpack .../00-libapr1_1.6.3-2_amd64.deb ...Preparing to unpack .../075-libwebp6_0.6.1-2_amd64.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/bg.js'Setting up python3-distutils (3.6.7-1~18.04) ...14% [Working] 5% [Waiting for headers] Running setup.py bdist_wheel for backcall ... -Unpacking libtheora0:amd64 (1.1.1+dfsg.1-14) ...Get:116 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libpoppler-cpp-dev amd64 0.62.0-2ubuntu2.5 [8680 B] Preparing to unpack .../010-liblcms2-2_2.9-1ubuntu0.1_amd64.deb ... 99% |███████████████████████████████▉| 215kB 5.8MB/s eta 0:00:01 70% |██████████████████████▋ | 5.0MB 6.0MB/s eta 0:00:01 25% |████████▏ | 501kB 5.9MB/s eta 0:00:01 68% |█████████████████████▊ | 5.5MB 5.9MB/s eta 0:00:01 60% |███████████████████▎ | 1.6MB 5.8MB/s eta 0:00:01 Preparing to unpack .../18-libubsan0_7.3.0-27ubuntu1~18.04_amd64.deb ...Unpacking fontconfig (2.12.6-0ubuntu2) ... 68% |█████████████████████▉ | 522kB 6.0MB/s eta 0:00:01 libc6-dev libcc1-0 libcilkrts5 libdpkg-perl libexpat1-dev libfakeroot libfile-fcntllock-perl libgcc-7-dev libisl19 libitm1Unpacking libdrm-nouveau2:amd64 (2.4.91-2) ... Running setup.py bdist_wheel for docopt ... -Copying '/usr/local/lib/python3.6/dist-packages/django_extensions/static/django_extensions/js/jquery.ajaxQueue.js'Get:50 http://archive.ubuntu.com/ubuntu bionic/main amd64 libmp3lame0 amd64 3.100-2 [136 kB]Selecting previously unselected package libcups2:amd64.54% [Waiting for headers] 3755 kB/s 8sGet:29 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libgs9-common all 9.26~dfsg+0-0ubuntu0.18.04.3 [5094 kB]Preparing to unpack .../030-ghostscript_9.26~dfsg+0-0ubuntu0.18.04.3_amd64.deb ... Running setup.py bdist_wheel for pytest-env ... - Stored in directory: /root/.cache/pip/wheels/2e/0e/8e/c4625de9d6f723017996dd718d5fabe1c7bb1fbce7389d3bf6Get:120 http://archive.ubuntu.com/ubuntu bionic/main amd64 libwebpdemux2 amd64 0.6.1-2 [9472 B] libbluray-bdj firmware-crystalhd cups-common libfftw3-bin libfftw3-dev liblcms2-utils inkscape libjxr-tools opus-tools 55% |█████████████████▊ | 112kB 6.5MB/s eta 0:00:01 Preparing to unpack .../084-libchromaprint1_1.4.3-1_amd64.deb ...Selecting previously unselected package apache2-utils.89% [130 netpbm 2612 B/1017 kB 0%] 4630 kB/s 1sResolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.16.133 Applying documents.0016_auto_20170325_1558... OK 13% |████▏ | 409kB 5.5MB/s eta 0:00:01 Stored in directory: /root/.cache/pip/wheels/9b/04/dd/7daf4150b6d9b12949298737de9431a324d4b797ffd63f526ePreparing to unpack .../53-python3-setuptools_39.0.1-2_all.deb ...Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/LICENSE-SELECT2.md' Downloading https://files.pythonhosted.org/packages/4b/2a/0276479a4b3caeb8a8c1af2f8e4355746a97fab05a372e4a2c6a6b876165/idna-2.7-pySelecting previously unselected package i965-va-driver:amd64.Get:58 http://archive.ubuntu.com/ubuntu bionic/main amd64 python3-xdg all 0.25-4ubuntu1 [31.4 kB] Preparing to unpack .../064-libshine3_3.1.1-1_amd64.deb ...Enabling module status.67% [Waiting for headers] Downloading https://files.pythonhosted.org/packages/56/9d/1d02dd80bc4cd955f98980f28c5ee2200e1209292d5f9e9cc8d030d18655/certifi-201Unpacking libjpeg-turbo8:amd64 (1.5.2-0ubuntu5.18.04.1) ...Unpacking vdpau-driver-all:amd64 (1.1.1-3ubuntu1) ...98% [Waiting for headers] 4630 kB/s 0sSelecting previously unselected package poppler-data. 93% |██████████████████████████████ | 716kB 5.9MB/s eta 0:00:01 21% [22 libquadmath0 2613 B/133 kB 2%] Selecting previously unselected package libaprutil1:amd64.Get:21 http://archive.ubuntu.com/ubuntu bionic/multiverse Translation-en [108 kB] 82% |██████████████████████████▎ | 5.8MB 5.9MB/s eta 0:00:01 56% |██████████████████▎ | 4.1MB 6.0MB/s eta 0:00:01 Operations to perform:Get:129 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 mesa-vdpau-drivers amd64 18.0.5-0ubuntu0~18.04.1 [1902 kB] Get:71 http://archive.ubuntu.com/ubuntu bionic/main amd64 libtwolame0 amd64 0.3.13-3 [46.7 kB] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/vendor/select2/LICENSE-SELECT2.md'Selecting previously unselected package libjbig2dec0:amd64.Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/fa.js'Unpacking libharfbuzz0b:amd64 (1.7.2-1ubuntu1) ...Get:53 http://archive.ubuntu.com/ubuntu bionic/main amd64 libcroco3 amd64 0.6.12-2 [81.3 kB]erage-4.5.1 coveralls-1.5.1 dateparser-0.7.0 decorator-4.3.0 django-2.0.9 django-cors-headers-2.4.0 django-crispy-forms-1.7.2 django 100% |████████████████████████████████| 2.0MB 515kB/s Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/prepopulate_init.js'Get:126 http://archive.ubuntu.com/ubuntu bionic/main amd64 libxcb-xfixes0 amd64 1.13-1 [9340 B] Preparing to unpack .../49-python3-secretstorage_2.3.1-2_all.deb ...Receiving objects: 1% (56/5570) Setting up libdrm-radeon1:amd64 (2.4.91-2) ...98% [25 Sources store 0 B] 4229 kB/s 0s30% [Waiting for headers] Get:12 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 cpp amd64 4:7.3.0-3ubuntu2.1 [27.6 kB] 81% |██████████████████████████▏ | 1.6MB 5.8MB/s eta 0:00:01 Get:128 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 mesa-va-drivers amd64 18.0.5-0ubuntu0~18.04.1 [1778 kB] libva-x11-2 libva2 libvdpau1 libvorbis0a libvorbisenc2 libvorbisfile3 libvpx5 libwavpack1 libwebp6 libwebpdemux2 libwebpmux3Receiving objects: 21% (1170/5570), 676.01 KiB | 1.30 MiB/s libopus0 libpango-1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libpaper-utils libpaper1 libpciaccess0 libpixman-1-0Preparing to unpack .../40-libexpat1-dev_2.2.5-3_amd64.deb ...Selecting previously unselected package libisl19:amd64.Setting up libzvbi-common (0.2.35-13) ... 30% |█████████▊ | 2.2MB 5.9MB/s eta 0:00:01 Preparing to unpack .../122-libxcb-dri3-0_1.13-1_amd64.deb ...Preparing to unpack .../042-libpixman-1-0_0.34.0-2_amd64.deb ...Collecting pytest-django==3.4.3 (from -r requirements.txt (line 55)) libavahi-common3 libavcodec57 libavformat57 libavutil55 libbdplus0 libbluray2 libcairo2 libchromaprint1 libcroco3 libcrystalhd3Get:19 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libubsan0 amd64 7.3.0-27ubuntu1~18.04 [126 kB]Preparing to unpack .../119-libwebpdemux2_0.6.1-2_amd64.deb ...Get:74 http://archive.ubuntu.com/ubuntu bionic/main amd64 libvpx5 amd64 1.7.0-3 [798 kB] Downloading https://files.pythonhosted.org/packages/d4/6c/8a935e2c7b54a37714656d753e4187ee0631988184ed50c0cf6476858566/snowballste 19% |██████▏ | 1.6MB 4.6MB/s eta 0:00:02 Receiving objects: 20% (1114/5570) 43% [Working] 3755 kB/s 10s0.10-py3-none-any.whlAdding user `paperless' ...ple-1.1.8.tar.gzPreparing to unpack .../110-libnss3_2%3a3.35-2ubuntu2.1_amd64.deb ...Unpacking make (4.1-9.1ubuntu1) ... 97% |███████████████████████████████▍| 143kB 5.9MB/s eta 0:00:01 Setting up libwebp6:amd64 (0.6.1-2) ...37% [Waiting for headers] Collecting pytest-forked==0.2 (from -r requirements.txt (line 57))Unpacking libgsm1:amd64 (1.0.13-4build1) ...7% [Waiting for headers] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/hu.js'Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js'Unpacking liblsan0:amd64 (8.2.0-1ubuntu2~18.04) ...Get:73 http://archive.ubuntu.com/ubuntu bionic/main amd64 libvorbisenc2 amd64 1.3.5-4.2 [70.7 kB] Adding new group `ftpupload' (1001) ...Setting up ssl-cert (1.0.39) ...Setting up imagemagick-6-common (8:6.9.7.4+dfsg-16ubuntu6.4) ... 54% |█████████████████▋ | 4.4MB 5.3MB/s eta 0:00:01 Unpacking g++ (4:7.3.0-3ubuntu2.1) ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/fontawesome-webfont.ttf' 23% |███████▌ | 1.7MB 6.0MB/s eta 0:00:01 --2019-01-20 19:50:05-- https://raw.githubusercontent.com/bmsleight/paperless/master/scripts/lxc/lxc-install.shUnpacking libsensors4:amd64 (1:3.4.0-4) ...45% [Working] 4081 kB/s 12sReceiving objects: 31% (1727/5570), 2.15 MiB | 2.14 MiB/s 100% |████████████████████████████████| 1.0MB 946kB/s 49% |████████████████ | 3.6MB 6.0MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/css/autocomplete.css'28% [32 gsfonts 2875 kB/3120 kB 92%] 95% |██████████████████████████████▊ | 71kB 5.0MB/s eta 0:00:01 Downloading https://files.pythonhosted.org/packages/6a/8b/8517167a0adc45ce94d0873efb9487dd4cdeff7e10f96e837ad3d58f5837/django_filtPreparing to unpack .../045-libxrender1_1%3a0.9.10-1_amd64.deb ...Setting up libgdk-pixbuf2.0-common (2.36.11-2) ...Unpacking fonts-dejavu-core (2.37-1) ... Downloading https://files.pythonhosted.org/packages/59/59/4bc44158a767a6d66de18c4136c8aa90491d56cc951c10b74dd1e13213c9/langdetect-Preparing to unpack .../059-libgraphite2-3_1.3.11-2_amd64.deb ... 8% |██▋ | 655kB 2.3MB/s eta 0:00:04 Creating config file /etc/papersize with new versionGet:14 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libitm1 amd64 8.2.0-1ubuntu2~18.04 [28.1 kB]Selecting previously unselected package libxvidcore4:amd64.Selecting previously unselected package libzvbi-common.Unpacking tesseract-ocr (4.00~git2288-10f4998a-2) ... 100% |████████████████████████████████| 61kB 5.0MB/s Unpacking libfile-fcntllock-perl (0.22-3build2) ...Preparing to unpack .../121-libxcb-dri2-0_1.13-1_amd64.deb ...Selecting previously unselected package libdrm-radeon1:amd64.Setting up libsensors4:amd64 (1:3.4.0-4) ... Running setup.py bdist_wheel for langdetect ... donePreparing to unpack .../017-libogg0_1.3.2-1_amd64.deb ...s-1.2.1-py2.py3-none-any.whl50% [87 libmpg123-0 2613 B/125 kB 2%] 3755 kB/s 8s Installing from a newer Wheel-Version (1.1)Setting up libexpat1-dev:amd64 (2.2.5-3) ...Unpacking python3-distutils (3.6.7-1~18.04) ...Unpacking libpoppler-cpp0v5:amd64 (0.62.0-2ubuntu2.5) ...Selecting previously unselected package libx265-146:amd64.Selecting previously unselected package libmp3lame0:amd64.14% [Waiting for headers] Preparing to unpack .../116-librsvg2-common_2.40.20-2_amd64.deb ...Selecting previously unselected package manpages-dev.Selecting previously unselected package libpango-1.0-0:amd64. libwmf0.2-7 libx11-xcb1 libx264-152 libx265-146 libxcb-dri2-0 libxcb-dri3-0 libxcb-present0 libxcb-render0 libxcb-shm0 100% |████████████████████████████████| 112kB 4.1MB/s 99% |████████████████████████████████| 337kB 6.1MB/s eta 0:00:01 86% [Waiting for headers] Created symlink /etc/systemd/system/multi-user.target.wants/apache2.service → /lib/systemd/system/apache2.service. 43% |██████████████ | 3.5MB 6.0MB/s eta 0:00:01 Selecting previously unselected package libopenjp2-7:amd64./usr/local/lib/python3.6/dist-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from releas71% [Working] Selecting previously unselected package libwavpack1:amd64.Preparing to unpack .../01-libaprutil1_1.6.1-2_amd64.deb ...The following NEW packages will be installed:Selecting previously unselected package linux-libc-dev:amd64.update-alternatives: using /usr/bin/display-im6.q16 to provide /usr/bin/display-im6 (display-im6) in auto mode31% [Waiting for headers] 99% |████████████████████████████████| 2.0MB 6.2MB/s eta 0:00:01 Get:20 http://archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [151 kB] libavcodec57 libavformat57 libavutil55 libbdplus0 libbluray2 libcairo2 libchromaprint1 libcroco3 libcrystalhd3 libcups297% [Waiting for headers] update-alternatives: using /usr/bin/conjure-im6.q16 to provide /usr/bin/conjure-im6 (conjure-im6) in auto mode98% [137 tesseract-ocr 2613 B/218 kB 1%] 4630 kB/s 0sCreated symlink /etc/systemd/system/multi-user.target.wants/paperless-consumer.service → /etc/systemd/system/paperless-consumer.servAfter this operation, 8347 kB of additional disk space will be used.thon-levenshtein, fuzzywuzzy, gunicorn, imagesize, inotify-simple, ipython-genutils, pickleshare, ptyprocess, pexpect, parso, jedi, 28% [14 Translation-en store 0 B] [10 Sources 2419 kB/9051 kB 27%] [Waiting for headers] Collecting django-filter==2.0.0 (from -r requirements.txt (line 17))Selecting previously unselected package libltdl7:amd64.Preparing to unpack .../047-libcrystalhd3_1%3a0.0~git20110715.fdd2f19-12_amd64.deb ...Collecting psycopg2==2.7.6.1 (from -r requirements.txt (line 46))Selecting previously unselected package python3-secretstorage. 15% |█████ | 307kB 5.9MB/s eta 0:00:01 Setting up libxcb-sync1:amd64 (1.13-1) ...35% [59 libpango-1.0-0 2613 B/153 kB 2%] Preparing to unpack .../009-libjpeg8_8c-2ubuntu8_amd64.deb ...83% [Waiting for headers] 4630 kB/s 2sSelecting previously unselected package mesa-vdpau-drivers:amd64.43% [80 libxvidcore4 2613 B/200 kB 1%] 3755 kB/s 10s77% [Waiting for headers] Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/select2.full.min.js' 86% |███████████████████████████▌ | 2.3MB 5.9MB/s eta 0:00:01 Setting up libc-dev-bin (2.27-3ubuntu1) ...87% [Waiting for headers] 4630 kB/s 2s-0.7.5-py2.py3-none-any.whlCopying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/fonts/fontawesome-webfont.eot'Collecting apipkg==1.5 (from -r requirements.txt (line 3)) Applying auth.0005_alter_user_last_login_null... OK libvdpau1 libvorbis0a libvorbisenc2 libvorbisfile3 libvpx5 libwavpack1 libwebp6 libwebpdemux2 libwebpmux3 libwmf0.2-797% [20 Packages store 0 B] 4229 kB/s 0sGet:20 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libcilkrts5 amd64 7.3.0-27ubuntu1~18.04 [42.5 kB]Setting up libmagickcore-6.q16-3:amd64 (8:6.9.7.4+dfsg-16ubuntu6.4) ...36% [Waiting for headers] Adding new user `ftpupload' (1001) with group `ftpupload' ...Selecting previously unselected package libxcb-present0:amd64.98% [Working] 4944 kB/s 0sUnpacking libc-dev-bin (2.27-3ubuntu1) ... 76% |████████████████████████▌ | 6.2MB 6.0MB/s eta 0:00:01 96% [18 Packages store 0 B] [29 Translation-en 4135 B/175 kB 2%] 99% |████████████████████████████████| 112kB 6.5MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/vendor/select2/i18n/el.js' 6% |██ | 501kB 2.7MB/s eta 0:00:03 Unpacking libgme0:amd64 (0.6.2-1) ...Copying '/usr/local/lib/python3.6/dist-packages/rest_framework/static/rest_framework/img/glyphicons-halflings.png'Selecting previously unselected package libmagickcore-6.q16-3:amd64.-py2.py3-none-any.whl (177kB)Resolving deltas: 75% (2688/3560) Preparing to unpack .../097-libdrm-intel1_2.4.91-2_amd64.deb ...Preparing to unpack .../082-libavcodec57_7%3a3.4.4-0ubuntu0.18.04.1_amd64.deb ...11% [Waiting for headers] Get:35 http://archive.ubuntu.com/ubuntu bionic/main amd64 dh-python all 3.20180325ubuntu2 [89.2 kB] Setting up libgcc-7-dev:amd64 (7.3.0-27ubuntu1~18.04) ... liblsan0 libmpc3 libmpx2 libpython3-dev libpython3.6-dev libquadmath0 libstdc++-7-dev libtsan0 libubsan0 linux-libc-dev makeCopying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/js/collapse.min.js'.1.0-py2.py3-none-any.whl 26% |████████▍ | 2.1MB 5.1MB/s eta 0:00:02 0% [1 binutils-common 2613 B/193 kB 1%] Collecting prompt-toolkit==2.0.7 (from -r requirements.txt (line 47))Setting up libharfbuzz0b:amd64 (1.7.2-1ubuntu1) ... 70% |██████████████████████▊ | 1.4MB 5.9MB/s eta 0:00:01 11% |███▊ | 307kB 5.8MB/s eta 0:00:01 Unpacking libvorbis0a:amd64 (1.3.5-4.2) ...Unpacking libchromaprint1:amd64 (1.4.3-1) ...Unpacking python3-crypto (2.6.1-8ubuntu2) ... Downloading https://files.pythonhosted.org/packages/bc/bb/a24838832ba35baf52f32ab1a49b906b5f82fb7c76b2f6a7e35e140bac30/decorator-430% [Working] 92% |█████████████████████████████▊ | 7.5MB 5.8MB/s eta 0:00:01 Selecting previously unselected package cpp.38% [70 libtheora0 2613 B/170 kB 2%] Unpacking libpoppler-cpp-dev:amd64 (0.62.0-2ubuntu2.5) ... 15% |█████ | 1.3MB 3.3MB/s eta 0:00:03 91% [133 python3-pil 2613 B/328 kB 1%] 4630 kB/s 1s Stored in directory: /root/.cache/pip/wheels/de/c2/93/660fd5f7559049268ad2dc6d81c4e39e9e36518766eaf7e342 Running setup.py bdist_wheel for pytest-env ... done 20% |██████▋ | 1.5MB 5.9MB/s eta 0:00:01 Copying '/usr/local/lib/python3.6/dist-packages/django/contrib/admin/static/admin/img/LICENSE' 100% |████████████████████████████████| 204kB 2.8MB/s Get:4 http://archive.ubuntu.com/ubuntu bionic/universe amd64 proftpd-doc all 1.3.5e-1build1 [1165 kB] 65% |█████████████████████ | 4.6MB 5.9MB/s eta 0:00:01 Saving to: ‘lxc-install.sh’Get:47 http://archive.ubuntu.com/ubuntu bionic/main amd64 libcairo2 amd64 1.15.10-2 [580 kB] System load: 0.0 Users logged in: 1 + \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index fd9d57d4e..5dfcaf471 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -45,4 +45,5 @@ Contents troubleshooting contributing scanners + screenshots changelog diff --git a/docs/scanners.rst b/docs/scanners.rst index f933ab1e9..8f57a5a7a 100644 --- a/docs/scanners.rst +++ b/docs/scanners.rst @@ -17,13 +17,17 @@ that works right for you based on recommentations from other Paperless users. +---------+----------------+-----+-----+-----+----------------+ | Brother | `MFC-J6930DW`_ | yes | | | `ayounggun`_ | +---------+----------------+-----+-----+-----+----------------+ +| Brother | `MFC-J5910DW`_ | yes | | | `bmsleight`_ | ++---------+----------------+-----+-----+-----+----------------+ | Fujitsu | `ix500`_ | yes | | yes | `eonist`_ | +---------+----------------+-----+-----+-----+----------------+ .. _ADS-1500W: https://www.brother.ca/en/p/ads1500w .. _MFC-J6930DW: https://www.brother.ca/en/p/MFCJ6930DW +.. _MFC-J5910DW: https://www.brother.co.uk/printers/inkjet-printers/mfcj5910dw .. _ix500: http://www.fujitsu.com/us/products/computing/peripheral/scanners/scansnap/ix500/ .. _danielquinn: https://github.com/danielquinn .. _ayounggun: https://github.com/ayounggun +.. _bmsleight: https://github.com/bmsleight .. _eonist: https://github.com/eonist diff --git a/docs/screenshots.rst b/docs/screenshots.rst new file mode 100644 index 000000000..686b3d375 --- /dev/null +++ b/docs/screenshots.rst @@ -0,0 +1,16 @@ +.. _screenshots: + +Screenshots +=========== + +Once everything is set-up login to paperless using the web front-end + +.. image:: ../../_static/Screenshot_first_run_login.png + +Nice clean interface + +.. image:: ../../_static/Screenshot_first_logged.png + +Some documents loaded in via ftp or using the scanners ftp. + +.. image:: ../../_static/Screenshot_upload_and_scanned.png diff --git a/docs/setup.rst b/docs/setup.rst index e86fe9efe..5c0602294 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -43,6 +43,7 @@ You can go multiple routes with setting up and running Paperless: * The `bare metal route`_ * The `docker route`_ + * The `linux containers route`_ The `docker route`_ is quick & easy. @@ -53,7 +54,7 @@ should you want to contribute some code back. .. _docker route: setup-installation-docker_ .. _bare metal route: setup-installation-bare-metal_ .. _Docker Machine: https://docs.docker.com/machine/ - +.. _linux containers route: setup-installation-linux-containers_ .. _setup-installation-bare-metal: @@ -471,3 +472,37 @@ If you're using Docker, you can set a restart-policy_ in the Docker daemon. .. _restart-policy: https://docs.docker.com/engine/reference/commandline/run/#restart-policies-restart + + +.. _setup-installation-linux-containers: + +Linux Container Method +++++++++++++++++++++++ + +1. Install lxc + + .. caution:: + + This guide assumes that you use lxc on a ubuntu host, with + networking set-up to get ip addresses on your lan. + However, if this is set-up only two commands are needed. + +2. Lanch paperless container + +.. code:: bash + + $ lxc launch ubuntu: paperless + +3. Run install script within container + +.. code:: bash + + $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/danielquinn/paperless/master/scripts/lxc/lxc-install.sh && /bin/bash lxc-install.sh" + +The script will ask you for an ftpupload password. +As well as the super-user for paperless web front-end. +After around 10 mins, http://paperless.lan is ready and +ftp://paperless.lan with user: ftpupload + +See the `Installation recording <_static/lxc-install.svg>`_. + From cc0c34b977664e60f32a735bd4cb1c2a7e8363f4 Mon Sep 17 00:00:00 2001 From: bmsleight Date: Mon, 21 Jan 2019 18:49:40 +0000 Subject: [PATCH 006/101] Correct screenshot relative paths (another attempt) --- docs/screenshots.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/screenshots.rst b/docs/screenshots.rst index 686b3d375..53f564dd6 100644 --- a/docs/screenshots.rst +++ b/docs/screenshots.rst @@ -5,12 +5,12 @@ Screenshots Once everything is set-up login to paperless using the web front-end -.. image:: ../../_static/Screenshot_first_run_login.png +.. image:: ./_static/Screenshot_first_run_login.png Nice clean interface -.. image:: ../../_static/Screenshot_first_logged.png +.. image:: ./_static/Screenshot_first_logged.png Some documents loaded in via ftp or using the scanners ftp. -.. image:: ../../_static/Screenshot_upload_and_scanned.png +.. image:: ./_static/Screenshot_upload_and_scanned.png From f135ed12b052b7a5cc52381c6594b165802d4e8a Mon Sep 17 00:00:00 2001 From: bmsleight Date: Sun, 27 Jan 2019 15:16:19 +0000 Subject: [PATCH 007/101] scripts/lxc into docs/examples/lxc/ and assumption noted --- {scripts => docs/examples}/lxc/lxc-install.sh | 6 ++-- {scripts => docs/examples}/lxc/paperless.conf | 0 docs/setup.rst | 30 +++++++++++++------ 3 files changed, 24 insertions(+), 12 deletions(-) rename {scripts => docs/examples}/lxc/lxc-install.sh (92%) rename {scripts => docs/examples}/lxc/paperless.conf (100%) diff --git a/scripts/lxc/lxc-install.sh b/docs/examples/lxc/lxc-install.sh similarity index 92% rename from scripts/lxc/lxc-install.sh rename to docs/examples/lxc/lxc-install.sh index b6e37b18a..3788aa7e1 100644 --- a/scripts/lxc/lxc-install.sh +++ b/docs/examples/lxc/lxc-install.sh @@ -40,8 +40,8 @@ EOF systemctl restart proftpd -#Get Paperless from git (NB: currently fork) -su -c "cd /home/paperless ; git clone https://github.com/bmsleight/paperless" paperless +#Get Paperless from git +su -c "cd /home/paperless ; git clone https://github.com/danielquinn/paperless" paperless # Install Pip Requirements apt-get -y install python3-pip python3-venv @@ -64,7 +64,7 @@ su -c "cd /home/paperless/paperless/src/ ; ./manage.py createsuperuser" paperles su -c "cd /home/paperless/paperless/src/ ; ./manage.py collectstatic" paperless # Set-up apache -cp /home/paperless/paperless/scripts/lxc/paperless.conf /etc/apache2/sites-available/ +cp /home/paperless/paperless/docs/examples/lxc/paperless.conf /etc/apache2/sites-available/ a2dissite 000-default.conf a2ensite paperless.conf systemctl reload apache2 diff --git a/scripts/lxc/paperless.conf b/docs/examples/lxc/paperless.conf similarity index 100% rename from scripts/lxc/paperless.conf rename to docs/examples/lxc/paperless.conf diff --git a/docs/setup.rst b/docs/setup.rst index 543411fef..3b17b12b0 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -43,7 +43,7 @@ You can go multiple routes with setting up and running Paperless: * The `bare metal route`_ * The `docker route`_ - * The `linux containers route`_ + * A suggested `linux containers route`_ The `docker route`_ is quick & easy. @@ -51,6 +51,10 @@ The `docker route`_ is quick & easy. The `bare metal route`_ is a bit more complicated to setup but makes it easier should you want to contribute some code back. +The `linux containers route`_ is quick, but makes alot of assumptions on the +set-up, on the other hand the script could be used to install on a base +debian or ubuntu server. + .. _docker route: setup-installation-docker_ .. _bare metal route: setup-installation-bare-metal_ .. _Docker Machine: https://docs.docker.com/machine/ @@ -489,16 +493,24 @@ Docker daemon. .. _setup-installation-linux-containers: -Linux Container Method -++++++++++++++++++++++ +Suggested way for Linux Container Method +++++++++++++++++++++++++++++++++++++++++ -1. Install lxc +This method uses some rigid assumptions, for the best set-up:- - .. caution:: + * Ubuntu lts as the container + * Apache as the webserver + * proftpd as ftp server + * ftpupload as the ftp user + * paperless as the main user for website + * http://paperless.lan is the desired lan url + * LXC set to give ip addresses on your lan + +This could also be used as an install on a base debain/ubuntu server, +if the above assumptions are acceptable. + +1. Install lxc - This guide assumes that you use lxc on a ubuntu host, with - networking set-up to get ip addresses on your lan. - However, if this is set-up only two commands are needed. 2. Lanch paperless container @@ -510,7 +522,7 @@ Linux Container Method .. code:: bash - $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/danielquinn/paperless/master/scripts/lxc/lxc-install.sh && /bin/bash lxc-install.sh" + $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/danielquinn/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh" The script will ask you for an ftpupload password. As well as the super-user for paperless web front-end. From 1cbc233adb377a759c2b064adef77f64d8bb3c9b Mon Sep 17 00:00:00 2001 From: bmsleight Date: Sat, 2 Feb 2019 19:54:06 +0000 Subject: [PATCH 008/101] Troubleshooting: Viewing Consumer logs --- docs/troubleshooting.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst index 05b314004..99f3f1e55 100644 --- a/docs/troubleshooting.rst +++ b/docs/troubleshooting.rst @@ -73,3 +73,14 @@ For more information on this and situations like it, you should take a look at `Issue #118`_ as that's where this tip originated. .. _Issue #118: https://github.com/danielquinn/paperless/issues/118 + + +.. _troubleshooting-consumerlogs + + +Viewing Consumer logs +--------------------- + +.. code:: bash + + $ sudo journalctl -u paperless-consumer From 1f1a23d19f93f7dedf02f23b5cc09c668fea88ff Mon Sep 17 00:00:00 2001 From: Piotr Cichosz Date: Sat, 25 May 2019 19:02:34 +0200 Subject: [PATCH 009/101] changed urls for my fork - for easier testing changed sed separator as suggested in https://github.com/the-paperless-project/paperless/pull/500#discussion_r257806300 --- docs/examples/lxc/lxc-install.sh | 10 +++++----- docs/setup.rst | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/examples/lxc/lxc-install.sh b/docs/examples/lxc/lxc-install.sh index 3788aa7e1..fa7a83a1e 100644 --- a/docs/examples/lxc/lxc-install.sh +++ b/docs/examples/lxc/lxc-install.sh @@ -6,7 +6,7 @@ # Will set-up paperless, apache2 and proftpd # # lxc launch ubuntu: paperless -# lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/danielquinn/paperless/master/scripts/lxc/lxc-install.sh && /bin/bash lxc-install.sh" +# lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/maur/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh" # # @@ -41,7 +41,7 @@ systemctl restart proftpd #Get Paperless from git -su -c "cd /home/paperless ; git clone https://github.com/danielquinn/paperless" paperless +su -c "cd /home/paperless ; git clone https://github.com/maur/paperless" paperless # Install Pip Requirements apt-get -y install python3-pip python3-venv @@ -54,7 +54,7 @@ sed -e '/PAPERLESS_CONSUMPTION_DIR=/s/=.*/=\"\/home\/ftpupload\/\"/' \ # Update /etc/paperless.conf with PAPERLESS_SECRET_KEY SECRET=$(strings /dev/urandom | grep -o '[[:alnum:]]' | head -n 30 | tr -d '\n'; echo) -sed -i "s/#PAPERLESS_SECRET_KEY.*/PAPERLESS_SECRET_KEY=$SECRET/g" /etc/paperless.conf +sed -i "s/#PAPERLESS_SECRET_KEY.*/PAPERLESS_SECRET_KEY=$SECRET/" /etc/paperless.conf #Initialise the SQLite database su -c "cd /home/paperless/paperless/src/ ; ./manage.py migrate" paperless @@ -69,11 +69,11 @@ a2dissite 000-default.conf a2ensite paperless.conf systemctl reload apache2 -sed -e "s/home\/paperless\/project\/virtualenv\/bin\/python/usr\/bin\/python3/" \ +sed -e "s:home/paperless/project/virtualenv/bin/python:usr/bin/python3:" \ /home/paperless/paperless/scripts/paperless-consumer.service \ >/etc/systemd/system/paperless-consumer.service -sed -i "s/\/home\/paperless\/project\/src\/manage.py/\/home\/paperless\/paperless\/src\/manage.py/" \ +sed -i "s:/home/paperless/project/src/manage.py:/home/paperless/paperless/src/manage.py:" \ /etc/systemd/system/paperless-consumer.service diff --git a/docs/setup.rst b/docs/setup.rst index 3b17b12b0..0a0d78d70 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -522,7 +522,7 @@ if the above assumptions are acceptable. .. code:: bash - $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/danielquinn/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh" + $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/maur/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh" The script will ask you for an ftpupload password. As well as the super-user for paperless web front-end. From cd3e8f7f8a6c1fee297a0b0583f2bf7a7c3f971c Mon Sep 17 00:00:00 2001 From: Piotr Cichosz Date: Sun, 26 May 2019 23:24:27 +0200 Subject: [PATCH 010/101] allow to set email and password as lxc-install.sh parameter --- docs/examples/lxc/lxc-install.sh | 128 +++++++++++++----- .../create_superuser_with_password.py | 38 ++++++ 2 files changed, 135 insertions(+), 31 deletions(-) create mode 100644 management/commands/create_superuser_with_password.py diff --git a/docs/examples/lxc/lxc-install.sh b/docs/examples/lxc/lxc-install.sh index fa7a83a1e..830777d1e 100644 --- a/docs/examples/lxc/lxc-install.sh +++ b/docs/examples/lxc/lxc-install.sh @@ -6,39 +6,96 @@ # Will set-up paperless, apache2 and proftpd # # lxc launch ubuntu: paperless -# lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/maur/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh" +# lxc exec paperless -- sh -c "sudo apt-get update && sudo apt-get install -y wget" +# lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/maur/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh --email " # # - -# Add paperless user with no password -adduser --disabled-password --gecos "" paperless -# Add ftpupload -adduser --disabled-password --gecos "" ftpupload -echo "Set ftpupload password: " -passwd ftpupload -# Allow paperless group to access -adduser paperless ftpupload -chmod g+w /home/ftpupload +set +e +PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9+@%^{} | head -c20;echo;) +EMAIL= + +function displayHelp() { + echo "available parameters: + -e | --email + -p | --password + " +} + +POSITIONAL=() +while [[ $# -gt 0 ]] +do +key="$1" +i=$key + +case $i in + -e|--email) + EMAIL="${2}" + shift + shift + ;; + -p|--password) + PASSWORD="${2}" + shift + shift + ;; + --default|-h|--help) + shift + displayHelp + exit 0 + ;; + *) + echo "argument: $i not recognized" + exit 2 + ;; +esac +done +set -- "${POSITIONAL[@]}" # restore positional parameters + +if [ -z $EMAIL ]; then + echo "missing email, try running with -h " + exit 3 +fi + +if [ $(grep -c paperless /etc/passwd) -eq 0 ]; then + # Add paperless user with no password + adduser --disabled-password --gecos "" paperless +fi + +if [ $(grep -c ftpupload /etc/passwd) -eq 0 ]; then + # Add ftpupload + adduser --disabled-password --gecos "" ftpupload + echo "Set ftpupload password: " + #passwd ftpupload + #TODO: generate some password and allow parameter + echo "ftpupload:ftpuploadpassword" | chpasswd +fi + +if [ $(id -nG paperless | grep -Fcw ftpupload) -eq 0 ]; then + # Allow paperless group to access + adduser paperless ftpupload + chmod g+w /home/ftpupload +fi # Get apt up to date apt-get update # Needed for plain Paperless -apt-get -y install unpaper gnupg libpoppler-cpp-dev python3-pyocr tesseract-ocr imagemagick optipng +apt-get -y install unpaper gnupg libpoppler-cpp-dev python3-pyocr tesseract-ocr imagemagick optipng git # Needed for Apache apt-get -y install apache2 libapache2-mod-wsgi-py3 -# Install ftp server and make sure all uplaoded files are owned by paperless -apt-get -y install proftpd -cat <> /etc/proftpd/proftpd.conf - - UserOwner paperless - GroupOwner paperless - +if [ ! -f /etc/proftpd/proftpd.conf -o $(grep -c paperless /etc/proftpd/proftpd.conf) -eq 0 ]; then + # Install ftp server and make sure all uplaoded files are owned by paperless + apt-get -y install proftpd + cat <> /etc/proftpd/proftpd.conf + + UserOwner paperless + GroupOwner paperless + EOF -systemctl restart proftpd - + systemctl restart proftpd +fi #Get Paperless from git su -c "cd /home/paperless ; git clone https://github.com/maur/paperless" paperless @@ -58,16 +115,23 @@ sed -i "s/#PAPERLESS_SECRET_KEY.*/PAPERLESS_SECRET_KEY=$SECRET/" /etc/paperless #Initialise the SQLite database su -c "cd /home/paperless/paperless/src/ ; ./manage.py migrate" paperless +echo "if superuser doesn't exists, create one with login: paperless and password: ${PASSWORD}" #Create a user for your Paperless instance -su -c "cd /home/paperless/paperless/src/ ; ./manage.py createsuperuser" paperless -# 167 static files copied to '/home/paperless/paperless/static'. -su -c "cd /home/paperless/paperless/src/ ; ./manage.py collectstatic" paperless - -# Set-up apache -cp /home/paperless/paperless/docs/examples/lxc/paperless.conf /etc/apache2/sites-available/ -a2dissite 000-default.conf -a2ensite paperless.conf -systemctl reload apache2 +su -c "cd /home/paperless/paperless/src/ ; echo ./manage.py create_superuser_with_password --username paperless --email ${EMAIL} --password ${PASSWORD} --preserve" paperless +su -c "cd /home/paperless/paperless/src/ ; ./manage.py create_superuser_with_password --username paperless --email ${EMAIL} --password ${PASSWORD} --preserve" paperless + +if [ ! -d /home/paperless/paperless/static ]; then + # 167 static files copied to '/home/paperless/paperless/static'. + su -c "cd /home/paperless/paperless/src/ ; ./manage.py collectstatic" paperless +fi + +if [ ! -f /etc/apache2/sites-available/paperless.conf ]; then + # Set-up apache + cp /home/paperless/paperless/docs/examples/lxc/paperless.conf /etc/apache2/sites-available/ + a2dissite 000-default.conf + a2ensite paperless.conf + systemctl reload apache2 +fi sed -e "s:home/paperless/project/virtualenv/bin/python:usr/bin/python3:" \ /home/paperless/paperless/scripts/paperless-consumer.service \ @@ -83,4 +147,6 @@ systemctl start paperless-consumer # convert-im6.q16: not authorized # Security risk ? # https://stackoverflow.com/questions/42928765/convertnot-authorized-aaaa-error-constitute-c-readimage-453 -mv /etc/ImageMagick-6/policy.xml /etc/ImageMagick-6/policy.xmlout +if [ -f /etc/ImageMagick-6/policy.xml ]; then + mv /etc/ImageMagick-6/policy.xml /etc/ImageMagick-6/policy.xmlout +fi diff --git a/management/commands/create_superuser_with_password.py b/management/commands/create_superuser_with_password.py new file mode 100644 index 000000000..830c1e167 --- /dev/null +++ b/management/commands/create_superuser_with_password.py @@ -0,0 +1,38 @@ +from django.contrib.auth.management.commands import createsuperuser +from django.core.management import CommandError + + +class Command(createsuperuser.Command): + help = 'Crate a superuser, and allow password to be provided' + + def add_arguments(self, parser): + super(Command, self).add_arguments(parser) + parser.add_argument( + '--password', dest='password', default=None, + help='Specifies the password for the superuser.', + ) + parser.add_argument( + '--preserve', dest='preserve', default=False, action='store_true', + help='Exit normally if the user already exists.', + ) + + def handle(self, *args, **options): + password = options.get('password') + username = options.get('username') + database = options.get('database') + + if password and not username: + raise CommandError("--username is required if specifying --password") + + if username and options.get('preserve'): + exists = self.UserModel._default_manager.db_manager(database).filter(username=username).exists() + if exists: + self.stdout.write("User exists, exiting normally due to --preserve") + return + + super(Command, self).handle(*args, **options) + + if password: + user = self.UserModel._default_manager.db_manager(database).get(username=username) + user.set_password(password) + user.save() From 467bb013e2353231774fe24be32a659b8e60d62e Mon Sep 17 00:00:00 2001 From: Piotr Cichosz Date: Mon, 27 May 2019 00:04:57 +0200 Subject: [PATCH 011/101] check if lxc-install executed as root --- docs/examples/lxc/lxc-install.sh | 4 ++++ docs/setup.rst | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/examples/lxc/lxc-install.sh b/docs/examples/lxc/lxc-install.sh index 830777d1e..d8fb06372 100644 --- a/docs/examples/lxc/lxc-install.sh +++ b/docs/examples/lxc/lxc-install.sh @@ -55,6 +55,10 @@ if [ -z $EMAIL ]; then echo "missing email, try running with -h " exit 3 fi +if [[ $(/usr/bin/id -u) -ne 0 ]]; then + echo "Not running as root" + exit +fi if [ $(grep -c paperless /etc/passwd) -eq 0 ]; then # Add paperless user with no password diff --git a/docs/setup.rst b/docs/setup.rst index 0a0d78d70..ac1b250e4 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -522,7 +522,7 @@ if the above assumptions are acceptable. .. code:: bash - $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/maur/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh" + $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/maur/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh --email" The script will ask you for an ftpupload password. As well as the super-user for paperless web front-end. From 0eb073b6d283d73643e823de38149c07a4a544dd Mon Sep 17 00:00:00 2001 From: Piotr Cichosz Date: Mon, 27 May 2019 00:18:37 +0200 Subject: [PATCH 012/101] change urls to the-paperless-project repo --- docs/examples/lxc/lxc-install.sh | 4 ++-- docs/setup.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/lxc/lxc-install.sh b/docs/examples/lxc/lxc-install.sh index d8fb06372..41ce375af 100644 --- a/docs/examples/lxc/lxc-install.sh +++ b/docs/examples/lxc/lxc-install.sh @@ -7,7 +7,7 @@ # # lxc launch ubuntu: paperless # lxc exec paperless -- sh -c "sudo apt-get update && sudo apt-get install -y wget" -# lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/maur/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh --email " +# lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/the-paperless-project/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh --email " # # set +e @@ -102,7 +102,7 @@ EOF fi #Get Paperless from git -su -c "cd /home/paperless ; git clone https://github.com/maur/paperless" paperless +su -c "cd /home/paperless ; git clone https://github.com/the-paperless-project/paperless" paperless # Install Pip Requirements apt-get -y install python3-pip python3-venv diff --git a/docs/setup.rst b/docs/setup.rst index ac1b250e4..e679d0b30 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -522,7 +522,7 @@ if the above assumptions are acceptable. .. code:: bash - $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/maur/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh --email" + $ lxc exec paperless -- sh -c "wget https://raw.githubusercontent.com/the-paperless-project/paperless/master/docs/examples/lxc/lxc-install.sh && /bin/bash lxc-install.sh --email" The script will ask you for an ftpupload password. As well as the super-user for paperless web front-end. From 54299d6362b5f2c87663f86d828a54556ba0fbe7 Mon Sep 17 00:00:00 2001 From: Lukas Winkler Date: Tue, 4 Jun 2019 10:54:04 +0200 Subject: [PATCH 013/101] update German readme --- README-de.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README-de.md b/README-de.md index e3314836a..06ffd5393 100644 --- a/README-de.md +++ b/README-de.md @@ -22,9 +22,9 @@ Paperless steuert nicht deinen Scanner, es hilft nur damit umzugehen, was der Sc 1. Kaufe einen Dokumentenscanner, der an einen Ort in deinem Netzwerk schreiben kann. Wenn du Inspirationen brauchst, schau in die [Scannerempfehlungen](https://paperless.readthedocs.io/en/latest/scanners.html). 2. Stelle "Scanne zu FTP" oder ähnliches ein. Es sollte möglich sein, eingescannte Bilder ohne etwas tun zu müssen an einen Server hochzuladen. Natürlich kannst du auch die einscannte Datei händisch hochladen, wenn der Scanner automatisches Hochladen nicht unterstützt. Paperless ist es egal, wie die Dokumente in seinen lokalen Konsumordner gelangen. -3. Besitze einen Zielserver, lasse das Papierless-Konsumskript laufen, um die Datei mit OCR zu versehen und sie in einer lokalen Datenbank zu indexieren. +3. Besitze einen Zielserver, lasse das Paperless-Konsumskript laufen, um die Datei mit OCR zu versehen und sie in einer lokalen Datenbank zu indexieren. 4. Benutze die Weboberfläche, um die Datenbank zu durchforsten und zu finden, was du suchst. -5. Lade die PDF-Datei, die du brauchst/möchtest über die Weboberfläche herunter und mach was auch immer du willst damit. Du kannst es auch drucken und versenden, so als wäre es das Original. In den meisten Fällen, wird das niemanden interessieren oder bemerken. +5. Lade die PDF-Datei, die du brauchst/möchtest über die Weboberfläche herunter und mach was auch immer du willst damit. Du kannst es auch drucken und versenden, so als wäre es das Original. In den meisten Fällen wird das niemanden interessieren oder bemerken. Hier das, was du bekommt: @@ -58,12 +58,13 @@ Dieses Projekt wurde um 2015 gestartet und es gibt viele Leute, die es verwenden Ich entwickle keine neuen Funktionen mehr für Paperless, weil es genau das tut, was ich brauche und meine Aufmerksamkeit meinem neuesten Projekt [Aletheia](https://github.com/danielquinn/aletheia) gewidmet ist. Ich verlasse jedoch nicht das Projekt. Ich bin glücklich damit, Pull Requests zu begutachten und Fragen im Issue-Bereich zu beantworten. Wenn du ein Entwickler bist und eine neue Funktion willst, reihe sie in den Issues ein und/oder sende einen PR! Ich bin glücklich damit, neue Sachen hinzuzufügen, habe aber einfach nicht die Zeit, sie selbst zu erarbeiten. -## Verknüpfte Prjekte +## Verknüpfte Projekte Paperless gibt es bereits seit einer Weile und Leute haben damit angefangen, Sachen rund um Paperless zu entwickeln. Wenn du einer dieser Menschen bist, kannst du dein Projekt zu dieser Liste hinzufügen: * [Paperless Desktop](https://github.com/thomasbrueggemann/paperless-desktop): Eine Desktop-Oberfläche für deine Paperless-Installation. Läuft auf Mac, Linux und Windows. * [ansible-role-paperless](https://github.com/ovv/ansible-role-paperless): Eine einfache Möglichkeit, Paperless via Ansible laufen zu lassen. +* [paperless-cli](https://github.com/stgarf/paperless-cli): Ein golang Kommandozeilenprogramm, welches mit Paperless interagiert. ## Ähnliche Projekte @@ -73,7 +74,7 @@ Es gibt da draußen auch das Projekt [Mayan EDMS](https://mayan.readthedocs.org/ ## Wichtiger Hinweis -Dokumentenscanner werden typerweise verwendet, um sensible Dokumente zu scannen. Dinge wie die Sozialversicherungsnummer, Steueraufzeichnungen, Rechnungen, etc. Während Paperless die Originaldateien über das Konsumskript verschlüsselt, sind die OCR-Texte *nicht* verschlüsselt und demnach in Klartext gespeichert (es muss durchsuchbar sein, also wenn jemand eine Idee hat, wie man das mit verschlüsselten Daten tun kann: Ich bin ganz Ohr). Das bedeutet, dass Paperless niemals auf einem nicht vertrauten Host laufen sollte. Stattdessen empfehle ich, wenn du es verwenden willst, es lokal auf einem Server in deinem Zuhause laufen zu lassen. +Dokumentenscanner werden typischerweise verwendet, um sensible Dokumente zu scannen. Dinge wie die Sozialversicherungsnummer, Steueraufzeichnungen, Rechnungen, etc. Während Paperless die Originaldateien über das Konsumskript verschlüsselt, sind die OCR-Texte *nicht* verschlüsselt und demnach in Klartext gespeichert (es muss durchsuchbar sein, also wenn jemand eine Idee hat, wie man das mit verschlüsselten Daten tun kann: Ich bin ganz Ohr). Das bedeutet, dass Paperless niemals auf einem nicht vertrauten Host laufen sollte. Stattdessen empfehle ich, wenn du es verwenden willst, es lokal auf einem Server in deinem Zuhause laufen zu lassen. ## Spenden From 919bb3cf80c155e8e0f6686d7bfad87a670e7f81 Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Thu, 18 Jul 2019 10:54:55 +0300 Subject: [PATCH 014/101] Docker Hub Test 0 --- .docker-hub-test | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .docker-hub-test diff --git a/.docker-hub-test b/.docker-hub-test new file mode 100644 index 000000000..e69de29bb From 5305c134927271dd194b5f32d46dcc11aa0f9ead Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Thu, 18 Jul 2019 14:10:25 +0300 Subject: [PATCH 015/101] Docker Hub Test 1 --- .docker-hub-test | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .docker-hub-test diff --git a/.docker-hub-test b/.docker-hub-test deleted file mode 100644 index e69de29bb..000000000 From 66777bccaf4e895cedb4c3e78e9cf051c7d1def5 Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Thu, 18 Jul 2019 14:18:54 +0300 Subject: [PATCH 016/101] Docker Hub test 2 --- .docker-hub-test | 1 + 1 file changed, 1 insertion(+) create mode 100644 .docker-hub-test diff --git a/.docker-hub-test b/.docker-hub-test new file mode 100644 index 000000000..6c2dff5ab --- /dev/null +++ b/.docker-hub-test @@ -0,0 +1 @@ +Docker Hub test 2 From 39754792c8babf758902555f3cbdf90d5e4467ee Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Wed, 24 Jul 2019 10:38:00 -0900 Subject: [PATCH 017/101] Add whitenoise and brotli as prerequesite for improving performance of static file serving Additionally, pipenv Pipfile and Pipfile.lock as well as requirements.txt were updated to fullfil requirements of the above packages --- Pipfile | 102 +++++++++++++++++++++++++++------------- Pipfile.lock | 120 +++++++++++++++++++++++++++++++++++++++-------- requirements.txt | 2 + 3 files changed, 172 insertions(+), 52 deletions(-) diff --git a/Pipfile b/Pipfile index 84a410f51..e4f037b19 100644 --- a/Pipfile +++ b/Pipfile @@ -4,38 +4,76 @@ verify_ssl = true name = "pypi" [packages] -django = "<2.1,>=2.0" -pillow = "*" -coveralls = "*" -dateparser = "*" -django-cors-headers = "*" -django-crispy-forms = "*" -django-extensions = "*" -django-filter = "*" -djangorestframework = "*" -factory-boy = "*" -filemagic = "*" -fuzzywuzzy = {extras = ["speedup"], version = "==0.15.0"} -gunicorn = "*" -inotify-simple = "*" -langdetect = "*" -pdftotext = "*" -pyocr = "*" -python-dateutil = "*" -python-dotenv = "*" -python-gnupg = "*" -pytz = "*" -sphinx = "*" -tox = "*" -pycodestyle = "*" -pytest = "*" -pytest-cov = "*" -pytest-django = "*" -pytest-sugar = "*" -pytest-env = "*" -pytest-xdist = "*" -psycopg2 = "*" -djangoql = "*" +coveralls = "==1.5.1" +dateparser = "==0.7.0" +django-cors-headers = "==2.4.0" +django-crispy-forms = "==1.7.2" +django-extensions = "==2.1.4" +django-filter = "==2.1.0" +djangorestframework = "==3.9.1" +factory-boy = "==2.11.1" +filemagic = "==1.6" +fuzzywuzzy = {extras = ["speedup"],version = "==0.15.0"} +gunicorn = "==19.9.0" +langdetect = "==1.0.7" +pdftotext = "==2.1.1" +pyocr = "==0.5.3" +python-dateutil = "==2.7.5" +python-dotenv = "==0.10.1" +python-gnupg = "==0.4.4" +pytz = "==2018.9" +tox = "==3.7.0" +pycodestyle = "==2.4.0" +pytest = "==4.1.1" +pytest-cov = "==2.6.1" +pytest-django = "==3.4.5" +pytest-sugar = "==0.9.2" +pytest-env = "==0.6.2" +pytest-xdist = "==1.26.0" +psycopg2 = "==2.7.7" +djangoql = "==0.12.3" +whitenoise = "==4.1.3" +alabaster = "==0.7.12" +apipkg = "==1.5" +atomicwrites = "==1.2.1" +attrs = "==18.2.0" +certifi = "==2018.11.29" +chardet = "==3.0.4" +coverage = "==4.5.2" +docopt = "==0.6.2" +docutils = "==0.14" +execnet = "==1.5.0" +filelock = "==3.0.10" +idna = "==2.8" +imagesize = "==1.1.0" +more-itertools = "==5.0.0" +pluggy = "==0.8.1" +ply = "==3.11" +py = "==1.7.0" +pyparsing = "==2.3.1" +pytest-forked = "==1.0.1" +regex = "==2019.1.24" +requests = "==2.21.0" +six = "==1.12.0" +snowballstemmer = "==1.2.1" +sphinxcontrib-websupport = "==1.1.0" +termcolor = "==1.1.0" +text-unidecode = "==1.2" +toml = "==0.10.0" +tzlocal = "==1.5.1" +urllib3 = "==1.24.1" +virtualenv = "==16.3.0" +Django = "==2.0.10" +Pillow = "==5.4.1" +inotify_simple = "==1.1.8" +Sphinx = "==1.8.3" +Brotli = "==1.0.7" +Babel = "==2.6.0" +Faker = "==1.0.2" +Jinja2 = "==2.10" +MarkupSafe = "==1.1.0" +Pygments = "==2.3.1" +python-Levenshtein = "==0.12.0" [dev-packages] ipython = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 29032f6bb..9bc0f51f8 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "971e0c975821925652865e34eed1c668bc6f52bb8217b776f35e87a66c936e1b" + "sha256": "a87b309c10b65c7767094c13538e3233250022a2a93a6b0deea2ec779bc3161e" }, "pipfile-spec": 6, "requires": {}, @@ -19,6 +19,7 @@ "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" ], + "index": "pypi", "version": "==0.7.12" }, "apipkg": { @@ -26,6 +27,7 @@ "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6", "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c" ], + "index": "pypi", "version": "==1.5" }, "atomicwrites": { @@ -33,6 +35,7 @@ "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" ], + "index": "pypi", "version": "==1.2.1" }, "attrs": { @@ -40,6 +43,7 @@ "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" ], + "index": "pypi", "version": "==18.2.0" }, "babel": { @@ -47,13 +51,49 @@ "sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669", "sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23" ], + "index": "pypi", "version": "==2.6.0" }, + "brotli": { + "hashes": [ + "sha256:0538dc1744fd17c314d2adc409ea7d1b779783b89fd95bcfb0c2acc93a6ea5a7", + "sha256:0970a47f471782912d7705160b2b0a9306e68e6fadf9cffcaeb42d8f0951e26c", + "sha256:113f51658e6fe548dce4b3749f6ef6c24de4184ba9c10a909cbee4261c2a5da0", + "sha256:1e1aa9c4d1558889f42749c8baf846007953bfd32c8209230cf1cd1f5ef33495", + "sha256:2f2f4f78f29ac4a45d15b3d9fc3fd9705e0ad313a44b129f6e1d0c6916bad0e2", + "sha256:3269f6de1dd150fd0cce1c158b61ff5ac06d627fd3ae9c6ea03aed26fbbff7ea", + "sha256:50dd9ad2a2bb12da4e9002a438672d182f98e546e99952de80280a1e1729664f", + "sha256:5519a4b01b1a4f965083cbfa2ef2b9774c5a5f352341c47b50776ad109423d72", + "sha256:5eb27722d320370315971c427eb8aa7cc0791f2a458840d357ac653bd0ad3a14", + "sha256:5f06b4d5b6f58e5b5c220c2f23cad034dc5efa51b01fde2351ced1605bd980e2", + "sha256:72848d25a5f9e736db4af4512e0c3feecc094d57d241f8f1ae959115a2c39756", + "sha256:743001bca75f4a6b4454be3510feca46f9d61a0c782a9bc2bc684bdb245e279e", + "sha256:9d1c2dd27a1083fefd05b1b2f8df4a6bc2aaa6c21dd82cd41c8ae5e7c23a87f8", + "sha256:a13ce9b419fe9f277c63f700efb0e444331509d1881b5610d2ba7e9080606967", + "sha256:a19ef0952b9d2803df88dff07f45a6c92d5676afb9b8d69cf32232d684036d11", + "sha256:ad766ca8b8c1419b71a22756b45264f45725c86133dc80a7cbe30b6b78c75620", + "sha256:ad7963f261988ee0883816b6b9f206f11461c9b3cb5cfbca0c9ab5adc406d395", + "sha256:c16201060c5a3f8742e3deae759014251ac92f382f82bc2a41dc079ff18c3f24", + "sha256:c43b202f65891861a9a336984a103de25de235f756de69e32db893156f767013", + "sha256:c675c6cce4295cb1a692f3de7416aacace7314e064b94bc86e93aceefce7fd3e", + "sha256:d17cec0b992b1434f5f9df9986563605a4d1b1acd5574c87fc2ac014bcbd3316", + "sha256:dc91f6129953861a73d9a65c52a8dd682b561a9ebaf65283541645cab6489917", + "sha256:e2f4cbd1760d2bf2f30e396c2301999aab0191aec031a6a8a04950b2f575a536", + "sha256:f192e6d3556714105c10486bbd6d045e38a0c04d9da3cef21e0a8dfd8e162df4", + "sha256:f775b07026af2b1b0b5a8b05e41571cdcf3a315a67df265d60af301656a5425b", + "sha256:f969ec7f56ba9636679e69ca07fba548312ccaca37412ee823c7f413541ad7e0", + "sha256:f9dc52cd70907aafb99a773b66b156f2f995c7a0d284397c487c8b71ddbef2f9", + "sha256:fc7212e36ebeb81aebf7949c92897b622490d7c0e333a479c0395591e7994600" + ], + "index": "pypi", + "version": "==1.0.7" + }, "certifi": { "hashes": [ "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033" ], + "index": "pypi", "version": "==2018.11.29" }, "chardet": { @@ -61,6 +101,7 @@ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" ], + "index": "pypi", "version": "==3.0.4" }, "coverage": { @@ -97,6 +138,7 @@ "sha256:ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", "sha256:ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9" ], + "index": "pypi", "version": "==4.5.2" }, "coveralls": { @@ -174,6 +216,7 @@ "hashes": [ "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" ], + "index": "pypi", "version": "==0.6.2" }, "docutils": { @@ -182,6 +225,7 @@ "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" ], + "index": "pypi", "version": "==0.14" }, "execnet": { @@ -189,6 +233,7 @@ "sha256:a7a84d5fa07a089186a329528f127c9d73b9de57f1a1131b82bb5320ee651f6a", "sha256:fc155a6b553c66c838d1a22dba1dc9f5f505c43285a878c6f74a79c024750b83" ], + "index": "pypi", "version": "==1.5.0" }, "factory-boy": { @@ -204,6 +249,7 @@ "sha256:16342dca4d92bfc83bab6a7daf6650e0ab087605a66bc38f17523fdb01757910", "sha256:d871ea315b2dcba9138b8344f2c131a76ac62d6227ca39f69b0c889fec97376c" ], + "index": "pypi", "version": "==1.0.2" }, "filelock": { @@ -211,6 +257,7 @@ "sha256:b8d5ca5ca1c815e1574aee746650ea7301de63d87935b3463d26368b76e31633", "sha256:d610c1bb404daf85976d7a82eb2ada120f04671007266b708606565dd03b5be6" ], + "index": "pypi", "version": "==3.0.10" }, "filemagic": { @@ -244,6 +291,7 @@ "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], + "index": "pypi", "version": "==2.8" }, "imagesize": { @@ -251,6 +299,7 @@ "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5" ], + "index": "pypi", "version": "==1.1.0" }, "inotify-simple": { @@ -265,6 +314,7 @@ "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" ], + "index": "pypi", "version": "==2.10" }, "langdetect": { @@ -305,6 +355,7 @@ "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" ], + "index": "pypi", "version": "==1.1.0" }, "more-itertools": { @@ -313,6 +364,7 @@ "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9" ], + "index": "pypi", "version": "==5.0.0" }, "packaging": { @@ -370,6 +422,7 @@ "sha256:8ddc32f03971bfdf900a81961a48ccf2fb677cf7715108f85295c67405798616", "sha256:980710797ff6a041e9a73a5787804f848996ecaa6f8a1b1e08224a5894f2074a" ], + "index": "pypi", "version": "==0.8.1" }, "ply": { @@ -377,6 +430,7 @@ "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3", "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce" ], + "index": "pypi", "version": "==3.11" }, "psycopg2": { @@ -420,6 +474,7 @@ "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6" ], + "index": "pypi", "version": "==1.7.0" }, "pycodestyle": { @@ -435,6 +490,7 @@ "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d" ], + "index": "pypi", "version": "==2.3.1" }, "pyocr": { @@ -449,6 +505,7 @@ "sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a", "sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3" ], + "index": "pypi", "version": "==2.3.1" }, "pytest": { @@ -487,6 +544,7 @@ "sha256:260d03fbd38d5ce41a657759e8d19bc7c8cfa6d0dcfa36c0bc9742d33bc30742", "sha256:8d05c2e6f33cd4422571b2b1bb309720c398b0549cff499e3e4cde661875ab54" ], + "index": "pypi", "version": "==1.0.1" }, "pytest-sugar": { @@ -533,6 +591,7 @@ "hashes": [ "sha256:033a11de5e3d19ea25c9302d11224e1a1898fe5abd23c61c7c360c25195e3eb1" ], + "index": "pypi", "version": "==0.12.0" }, "pytz": { @@ -555,6 +614,7 @@ "sha256:e06eac198d9c76bcbe52b987b74ead0d353cfaa9f3d8cd907ec984f4bb20ea1e", "sha256:eee007ee39a02cb631b74f89f992766b9d7e952a750166f3e5a5baf8c328c070" ], + "index": "pypi", "version": "==2019.1.24" }, "requests": { @@ -562,6 +622,7 @@ "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" ], + "index": "pypi", "version": "==2.21.0" }, "six": { @@ -569,6 +630,7 @@ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], + "index": "pypi", "version": "==1.12.0" }, "snowballstemmer": { @@ -576,6 +638,7 @@ "sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", "sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89" ], + "index": "pypi", "version": "==1.2.1" }, "sphinx": { @@ -591,12 +654,14 @@ "sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", "sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" ], + "index": "pypi", "version": "==1.1.0" }, "termcolor": { "hashes": [ "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b" ], + "index": "pypi", "version": "==1.1.0" }, "text-unidecode": { @@ -604,6 +669,7 @@ "sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d", "sha256:801e38bd550b943563660a91de8d4b6fa5df60a542be9093f7abf819f86050cc" ], + "index": "pypi", "version": "==1.2" }, "toml": { @@ -611,6 +677,7 @@ "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" ], + "index": "pypi", "version": "==0.10.0" }, "tox": { @@ -625,6 +692,7 @@ "hashes": [ "sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e" ], + "index": "pypi", "version": "==1.5.1" }, "urllib3": { @@ -632,6 +700,7 @@ "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" ], + "index": "pypi", "version": "==1.24.1" }, "virtualenv": { @@ -639,7 +708,16 @@ "sha256:58c359370401e0af817fb0070911e599c5fdc836166306b04fd0f278151ed125", "sha256:729f0bcab430e4ef137646805b5b1d8efbb43fe53d4a0f33328624a84a5121f7" ], + "index": "pypi", "version": "==16.3.0" + }, + "whitenoise": { + "hashes": [ + "sha256:59d880d25d0e90bcc6554fe0504a11195bd2e59b3d690b6fb42a8040d4e67ef5", + "sha256:c9b7c47fdc1dba4d37bf2787a01a844dc7a521e174fcd22a2d429e0be65e1782" + ], + "index": "pypi", + "version": "==4.1.3" } }, "develop": { @@ -652,18 +730,18 @@ }, "decorator": { "hashes": [ - "sha256:33cd704aea07b4c28b3eb2c97d288a06918275dac0ecebdaf1bc8a48d98adb9e", - "sha256:cabb249f4710888a2fc0e13e9a16c343d932033718ff62e1e9bc93a9d3a9122b" + "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", + "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6" ], - "version": "==4.3.2" + "version": "==4.4.0" }, "ipython": { "hashes": [ - "sha256:6a9496209b76463f1dec126ab928919aaf1f55b38beb9219af3fe202f6bbdd12", - "sha256:f69932b1e806b38a7818d9a1e918e5821b685715040b48e59c657b3c7961b742" + "sha256:11067ab11d98b1e6c7f0993506f7a5f8a91af420f7e82be6575fcb7a6ca372a0", + "sha256:60bc55c2c1d287161191cc2469e73c116d9b634cff25fe214a43cba7cec94c79" ], "index": "pypi", - "version": "==7.2.0" + "version": "==7.6.1" }, "ipython-genutils": { "hashes": [ @@ -674,25 +752,25 @@ }, "jedi": { "hashes": [ - "sha256:571702b5bd167911fe9036e5039ba67f820d6502832285cde8c881ab2b2149fd", - "sha256:c8481b5e59d34a5c7c42e98f6625e633f6ef59353abea6437472c7ec2093f191" + "sha256:53c850f1a7d3cfcd306cc513e2450a54bdf5cacd7604b74e42dd1f0758eaaf36", + "sha256:e07457174ef7cb2342ff94fa56484fe41cec7ef69b0059f01d3f812379cb6f7c" ], - "version": "==0.13.2" + "version": "==0.14.1" }, "parso": { "hashes": [ - "sha256:4b8f9ed80c3a4a3191aa3261505d868aa552dd25649cb13a7d73b6b7315edf2d", - "sha256:5a120be2e8863993b597f1c0437efca799e90e0793c98ae5d4e34ebd00140e31" + "sha256:63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc", + "sha256:666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c" ], - "version": "==0.3.2" + "version": "==0.5.1" }, "pexpect": { "hashes": [ - "sha256:2a8e88259839571d1251d278476f3eec5db26deb73a70be5ed5dc5435e418aba", - "sha256:3fbd41d4caf27fa4a377bfd16fef87271099463e6fa73e92a52f92dfee5d425b" + "sha256:2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1", + "sha256:9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb" ], "markers": "sys_platform != 'win32'", - "version": "==4.6.0" + "version": "==4.7.0" }, "pickleshare": { "hashes": [ @@ -703,11 +781,11 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:c1d6aff5252ab2ef391c2fe498ed8c088066f66bc64a8d5c095bbf795d9fec34", - "sha256:d4c47f79b635a0e70b84fdb97ebd9a274203706b1ee5ed44c10da62755cf3ec9", - "sha256:fd17048d8335c1e6d5ee403c3569953ba3eb8555d710bfc548faf0712666ea39" + "sha256:11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780", + "sha256:2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1", + "sha256:977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55" ], - "version": "==2.0.7" + "version": "==2.0.9" }, "ptyprocess": { "hashes": [ @@ -721,6 +799,7 @@ "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d" ], + "index": "pypi", "version": "==2.3.1" }, "six": { @@ -728,6 +807,7 @@ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], + "index": "pypi", "version": "==1.12.0" }, "traitlets": { diff --git a/requirements.txt b/requirements.txt index 0885215c4..a643a88cf 100755 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ apipkg==1.5 atomicwrites==1.2.1 attrs==18.2.0 babel==2.6.0 +brotli==1.0.7 certifi==2018.11.29 chardet==3.0.4 coverage==4.5.2 @@ -68,3 +69,4 @@ tox==3.7.0 tzlocal==1.5.1 urllib3==1.24.1 virtualenv==16.3.0 +whitenoise==4.1.3 From 528b4ac2f0ab8a9973eafecd233d74edbc4bb381 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Wed, 24 Jul 2019 13:26:28 -0900 Subject: [PATCH 018/101] Activate whitenoise and static file compression and caching --- src/paperless/settings.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/paperless/settings.py b/src/paperless/settings.py index 917d1e64f..ce387be07 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -62,6 +62,7 @@ def __get_boolean(key, default="NO"): # Application definition INSTALLED_APPS = [ + "whitenoise.runserver_nostatic", "django.contrib.auth", "django.contrib.contenttypes", @@ -92,6 +93,7 @@ def __get_boolean(key, default="NO"): MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', + 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', @@ -101,6 +103,9 @@ def __get_boolean(key, default="NO"): 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] +# Enable whitenoise compression and caching +STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' + # We allow CORS from localhost:8080 CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "localhost:8080").split(",")) From 4107323a766d32ea2d5226d7292a246214fe53ed Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Wed, 24 Jul 2019 13:34:05 -0900 Subject: [PATCH 019/101] Enable static file collection in docker image --- scripts/docker-entrypoint.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index 5cfcd4023..303d1b8de 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -55,10 +55,15 @@ migrations() { fi } +collectstatic() { + sudo -HEu paperless "/usr/src/paperless/src/manage.py" "collectstatic" "--clear" "--no-input" +} + initialize() { map_uidgid set_permissions migrations + collectstatic } install_languages() { From 7e77c5ec31baad5bb4c31336b3840b274f58e7fb Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Thu, 25 Jul 2019 00:55:20 +0200 Subject: [PATCH 020/101] Add static file collection instruction to bare-metal setup guide as it is necessary for whitenoise static file serving --- docs/setup.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/setup.rst b/docs/setup.rst index 9c665a607..da17c38e8 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -82,21 +82,22 @@ Standard (Bare Metal) this is the default. 4. Initialise the SQLite database with ``./manage.py migrate``. -5. Create a user for your Paperless instance with +5. Collect the static files for the webserver with ``./manage.py collectstatic``. +6. Create a user for your Paperless instance with ``./manage.py createsuperuser``. Follow the prompts to create your user. -6. Start the webserver with ``./manage.py runserver :``. +7. Start the webserver with ``./manage.py runserver :``. If no specific IP or port is given, the default is ``127.0.0.1:8000`` also known as http://localhost:8000/. You should now be able to visit your (empty) installation at `Paperless webserver`_ or whatever you chose before. You can login with the user/pass you created in #5. -7. In a separate window, change to the ``src`` directory in this repo again, +8. In a separate window, change to the ``src`` directory in this repo again, but this time, you should start the consumer script with ``./manage.py document_consumer``. -8. Scan something or put a file into the ``CONSUMPTION_DIR``. -9. Wait a few minutes -10. Visit the document list on your webserver, and it should be there, indexed +9. Scan something or put a file into the ``CONSUMPTION_DIR``. +10. Wait a few minutes +11. Visit the document list on your webserver, and it should be there, indexed and downloadable. .. caution:: From 2569067ac8b361fc2f16e9b37715c4559548319e Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Mon, 5 Aug 2019 20:48:53 +0200 Subject: [PATCH 021/101] Remove exact versions from Pipfile: --- Pipfile | 140 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/Pipfile b/Pipfile index e4f037b19..02ef99bb2 100644 --- a/Pipfile +++ b/Pipfile @@ -4,76 +4,76 @@ verify_ssl = true name = "pypi" [packages] -coveralls = "==1.5.1" -dateparser = "==0.7.0" -django-cors-headers = "==2.4.0" -django-crispy-forms = "==1.7.2" -django-extensions = "==2.1.4" -django-filter = "==2.1.0" -djangorestframework = "==3.9.1" -factory-boy = "==2.11.1" -filemagic = "==1.6" -fuzzywuzzy = {extras = ["speedup"],version = "==0.15.0"} -gunicorn = "==19.9.0" -langdetect = "==1.0.7" -pdftotext = "==2.1.1" -pyocr = "==0.5.3" -python-dateutil = "==2.7.5" -python-dotenv = "==0.10.1" -python-gnupg = "==0.4.4" -pytz = "==2018.9" -tox = "==3.7.0" -pycodestyle = "==2.4.0" -pytest = "==4.1.1" -pytest-cov = "==2.6.1" -pytest-django = "==3.4.5" -pytest-sugar = "==0.9.2" -pytest-env = "==0.6.2" -pytest-xdist = "==1.26.0" -psycopg2 = "==2.7.7" -djangoql = "==0.12.3" -whitenoise = "==4.1.3" -alabaster = "==0.7.12" -apipkg = "==1.5" -atomicwrites = "==1.2.1" -attrs = "==18.2.0" -certifi = "==2018.11.29" -chardet = "==3.0.4" -coverage = "==4.5.2" -docopt = "==0.6.2" -docutils = "==0.14" -execnet = "==1.5.0" -filelock = "==3.0.10" -idna = "==2.8" -imagesize = "==1.1.0" -more-itertools = "==5.0.0" -pluggy = "==0.8.1" -ply = "==3.11" -py = "==1.7.0" -pyparsing = "==2.3.1" -pytest-forked = "==1.0.1" -regex = "==2019.1.24" -requests = "==2.21.0" -six = "==1.12.0" -snowballstemmer = "==1.2.1" -sphinxcontrib-websupport = "==1.1.0" -termcolor = "==1.1.0" -text-unidecode = "==1.2" -toml = "==0.10.0" -tzlocal = "==1.5.1" -urllib3 = "==1.24.1" -virtualenv = "==16.3.0" -Django = "==2.0.10" -Pillow = "==5.4.1" -inotify_simple = "==1.1.8" -Sphinx = "==1.8.3" -Brotli = "==1.0.7" -Babel = "==2.6.0" -Faker = "==1.0.2" -Jinja2 = "==2.10" -MarkupSafe = "==1.1.0" -Pygments = "==2.3.1" -python-Levenshtein = "==0.12.0" +coveralls = "*" +dateparser = "*" +django-cors-headers = "*" +django-crispy-forms = "*" +django-extensions = "*" +django-filter = "*" +djangorestframework = "*" +factory-boy = "*" +filemagic = "*" +fuzzywuzzy = {extras = ["speedup"], version = "==0.15.0"} +gunicorn = "*" +langdetect = "*" +pdftotext = "*" +pyocr = "*" +python-dateutil = "*" +python-dotenv = "*" +python-gnupg = "*" +pytz = "*" +tox = "*" +pycodestyle = "*" +pytest = "*" +pytest-cov = "*" +pytest-django = "*" +pytest-sugar = "*" +pytest-env = "*" +pytest-xdist = "*" +psycopg2 = "*" +djangoql = "*" +whitenoise = "*" +alabaster = "*" +apipkg = "*" +atomicwrites = "*" +attrs = "*" +certifi = "*" +chardet = "*" +coverage = "*" +docopt = "*" +docutils = "*" +execnet = "*" +filelock = "*" +idna = "*" +imagesize = "*" +more-itertools = "*" +pluggy = "*" +ply = "*" +py = "*" +pyparsing = "*" +pytest-forked = "*" +regex = "*" +requests = "*" +six = "*" +snowballstemmer = "*" +sphinxcontrib-websupport = "*" +termcolor = "*" +text-unidecode = "*" +toml = "*" +tzlocal = "*" +urllib3 = "*" +virtualenv = "*" +Django = "<2.1,>=2.0" +Pillow = "*" +inotify_simple = "*" +Sphinx = "*" +Brotli = "*" +Babel = "*" +Faker = "*" +Jinja2 = "*" +MarkupSafe = "*" +Pygments = "*" +python-Levenshtein = "*" [dev-packages] ipython = "*" From ce02473edb3a1286a30a731803913363d1cfbae9 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Tue, 6 Aug 2019 12:25:37 -0900 Subject: [PATCH 022/101] Remove specific versions from Pipfile and adjust Pipfile.lock and requirements.txt accordingly --- Pipfile | 48 +--- Pipfile.lock | 617 +++++++++++++++++++++++------------------------ requirements.txt | 102 ++++---- 3 files changed, 368 insertions(+), 399 deletions(-) mode change 100755 => 100644 requirements.txt diff --git a/Pipfile b/Pipfile index 02ef99bb2..fa7282ce3 100644 --- a/Pipfile +++ b/Pipfile @@ -4,6 +4,8 @@ verify_ssl = true name = "pypi" [packages] +django = "<2.1,>=2.0" +pillow = "*" coveralls = "*" dateparser = "*" django-cors-headers = "*" @@ -13,8 +15,9 @@ django-filter = "*" djangorestframework = "*" factory-boy = "*" filemagic = "*" -fuzzywuzzy = {extras = ["speedup"], version = "==0.15.0"} +fuzzywuzzy = {extras = ["speedup"],version = "==0.15.0"} gunicorn = "*" +inotify-simple = "*" langdetect = "*" pdftotext = "*" pyocr = "*" @@ -22,6 +25,7 @@ python-dateutil = "*" python-dotenv = "*" python-gnupg = "*" pytz = "*" +sphinx = "*" tox = "*" pycodestyle = "*" pytest = "*" @@ -33,47 +37,7 @@ pytest-xdist = "*" psycopg2 = "*" djangoql = "*" whitenoise = "*" -alabaster = "*" -apipkg = "*" -atomicwrites = "*" -attrs = "*" -certifi = "*" -chardet = "*" -coverage = "*" -docopt = "*" -docutils = "*" -execnet = "*" -filelock = "*" -idna = "*" -imagesize = "*" -more-itertools = "*" -pluggy = "*" -ply = "*" -py = "*" -pyparsing = "*" -pytest-forked = "*" -regex = "*" -requests = "*" -six = "*" -snowballstemmer = "*" -sphinxcontrib-websupport = "*" -termcolor = "*" -text-unidecode = "*" -toml = "*" -tzlocal = "*" -urllib3 = "*" -virtualenv = "*" -Django = "<2.1,>=2.0" -Pillow = "*" -inotify_simple = "*" -Sphinx = "*" -Brotli = "*" -Babel = "*" -Faker = "*" -Jinja2 = "*" -MarkupSafe = "*" -Pygments = "*" -python-Levenshtein = "*" +brotli = "*" [dev-packages] ipython = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 9bc0f51f8..249d3ff6e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "a87b309c10b65c7767094c13538e3233250022a2a93a6b0deea2ec779bc3161e" + "sha256": "229095b1d386419c9716ea1fbb7b42885d6ff686ca7266d317fbac78456754ac" }, "pipfile-spec": 6, "requires": {}, @@ -19,7 +19,6 @@ "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" ], - "index": "pypi", "version": "==0.7.12" }, "apipkg": { @@ -27,32 +26,28 @@ "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6", "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c" ], - "index": "pypi", "version": "==1.5" }, "atomicwrites": { "hashes": [ - "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", - "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" ], - "index": "pypi", - "version": "==1.2.1" + "version": "==1.3.0" }, "attrs": { "hashes": [ - "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", - "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" ], - "index": "pypi", - "version": "==18.2.0" + "version": "==19.1.0" }, "babel": { "hashes": [ - "sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669", - "sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23" + "sha256:af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", + "sha256:e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28" ], - "index": "pypi", - "version": "==2.6.0" + "version": "==2.7.0" }, "brotli": { "hashes": [ @@ -90,88 +85,86 @@ }, "certifi": { "hashes": [ - "sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7", - "sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033" + "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", + "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" ], - "index": "pypi", - "version": "==2018.11.29" + "version": "==2019.6.16" }, "chardet": { "hashes": [ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" ], - "index": "pypi", "version": "==3.0.4" }, "coverage": { "hashes": [ - "sha256:09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f", - "sha256:0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe", - "sha256:0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d", - "sha256:10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0", - "sha256:1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607", - "sha256:1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d", - "sha256:2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b", - "sha256:447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3", - "sha256:46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e", - "sha256:4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815", - "sha256:510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36", - "sha256:5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1", - "sha256:5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14", - "sha256:5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c", - "sha256:6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794", - "sha256:6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b", - "sha256:77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840", - "sha256:828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd", - "sha256:85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82", - "sha256:8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952", - "sha256:a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389", - "sha256:aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f", - "sha256:ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4", - "sha256:b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da", - "sha256:bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647", - "sha256:c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d", - "sha256:d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42", - "sha256:d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478", - "sha256:da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b", - "sha256:ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", - "sha256:ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9" - ], - "index": "pypi", - "version": "==4.5.2" + "sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6", + "sha256:0be0f1ed45fc0c185cfd4ecc19a1d6532d72f86a2bac9de7e24541febad72650", + "sha256:141f08ed3c4b1847015e2cd62ec06d35e67a3ac185c26f7635f4406b90afa9c5", + "sha256:19e4df788a0581238e9390c85a7a09af39c7b539b29f25c89209e6c3e371270d", + "sha256:23cc09ed395b03424d1ae30dcc292615c1372bfba7141eb85e11e50efaa6b351", + "sha256:245388cda02af78276b479f299bbf3783ef0a6a6273037d7c60dc73b8d8d7755", + "sha256:331cb5115673a20fb131dadd22f5bcaf7677ef758741312bee4937d71a14b2ef", + "sha256:386e2e4090f0bc5df274e720105c342263423e77ee8826002dcffe0c9533dbca", + "sha256:3a794ce50daee01c74a494919d5ebdc23d58873747fa0e288318728533a3e1ca", + "sha256:60851187677b24c6085248f0a0b9b98d49cba7ecc7ec60ba6b9d2e5574ac1ee9", + "sha256:63a9a5fc43b58735f65ed63d2cf43508f462dc49857da70b8980ad78d41d52fc", + "sha256:6b62544bb68106e3f00b21c8930e83e584fdca005d4fffd29bb39fb3ffa03cb5", + "sha256:6ba744056423ef8d450cf627289166da65903885272055fb4b5e113137cfa14f", + "sha256:7494b0b0274c5072bddbfd5b4a6c6f18fbbe1ab1d22a41e99cd2d00c8f96ecfe", + "sha256:826f32b9547c8091679ff292a82aca9c7b9650f9fda3e2ca6bf2ac905b7ce888", + "sha256:93715dffbcd0678057f947f496484e906bf9509f5c1c38fc9ba3922893cda5f5", + "sha256:9a334d6c83dfeadae576b4d633a71620d40d1c379129d587faa42ee3e2a85cce", + "sha256:af7ed8a8aa6957aac47b4268631fa1df984643f07ef00acd374e456364b373f5", + "sha256:bf0a7aed7f5521c7ca67febd57db473af4762b9622254291fbcbb8cd0ba5e33e", + "sha256:bf1ef9eb901113a9805287e090452c05547578eaab1b62e4ad456fcc049a9b7e", + "sha256:c0afd27bc0e307a1ffc04ca5ec010a290e49e3afbe841c5cafc5c5a80ecd81c9", + "sha256:dd579709a87092c6dbee09d1b7cfa81831040705ffa12a1b248935274aee0437", + "sha256:df6712284b2e44a065097846488f66840445eb987eb81b3cc6e4149e7b6982e1", + "sha256:e07d9f1a23e9e93ab5c62902833bf3e4b1f65502927379148b6622686223125c", + "sha256:e2ede7c1d45e65e209d6093b762e98e8318ddeff95317d07a27a2140b80cfd24", + "sha256:e4ef9c164eb55123c62411f5936b5c2e521b12356037b6e1c2617cef45523d47", + "sha256:eca2b7343524e7ba246cab8ff00cab47a2d6d54ada3b02772e908a45675722e2", + "sha256:eee64c616adeff7db37cc37da4180a3a5b6177f5c46b187894e633f088fb5b28", + "sha256:ef824cad1f980d27f26166f86856efe11eff9912c4fed97d3804820d43fa550c", + "sha256:efc89291bd5a08855829a3c522df16d856455297cf35ae827a37edac45f466a7", + "sha256:fa964bae817babece5aa2e8c1af841bebb6d0b9add8e637548809d040443fee0", + "sha256:ff37757e068ae606659c28c3bd0d923f9d29a85de79bf25b2b34b148473b5025" + ], + "version": "==4.5.4" }, "coveralls": { "hashes": [ - "sha256:ab638e88d38916a6cedbf80a9cd8992d5fa55c77ab755e262e00b36792b7cd6d", - "sha256:b2388747e2529fa4c669fb1e3e2756e4e07b6ee56c7d9fce05f35ccccc913aa0" + "sha256:9bc5a1f92682eef59f688a8f280207190d9a6afb84cef8f567fa47631a784060", + "sha256:fb51cddef4bc458de347274116df15d641a735d3f0a580a9472174e2e62f408c" ], "index": "pypi", - "version": "==1.5.1" + "version": "==1.8.2" }, "dateparser": { "hashes": [ - "sha256:940828183c937bcec530753211b70f673c0a9aab831e43273489b310538dff86", - "sha256:b452ef8b36cd78ae86a50721794bc674aa3994e19b570f7ba92810f4e0a2ae03" + "sha256:42d51be54e74a8e80a4d76d1fa6e4edd997098fce24ad2d94a2eab5ef247193e", + "sha256:78124c458c461ea7198faa3c038f6381f37588b84bb42740e91a4cbd260b1d09" ], "index": "pypi", - "version": "==0.7.0" + "version": "==0.7.1" }, "django": { "hashes": [ - "sha256:0292a7ad7d8ffc9cfc6a77f043d2e81f5bbc360c0c4a1686e130ef3432437d23", - "sha256:e89f613e3c1f7ff245ffee3560472f9fa9c07060b11f65e1de3cb763f8dcd4b9" + "sha256:665457d4146bbd34ae9d2970fa3b37082d7b225b0671bfd24c337458f229db78", + "sha256:bde46d4dbc410678e89bc95ea5d312dd6eb4c37d0fa0e19c9415cad94addf22f" ], "index": "pypi", - "version": "==2.0.10" + "version": "==2.0.13" }, "django-cors-headers": { "hashes": [ - "sha256:5545009c9b233ea7e70da7dbab7cb1c12afa01279895086f98ec243d7eab46fa", - "sha256:c4c2ee97139d18541a1be7d96fe337d1694623816d83f53cb7c00da9b94acae1" + "sha256:5b80bf0f8d7fc6e2bcb4f40781d5ff3661961bbf1982e52daec77241dea3b890", + "sha256:ebf3e2cf25aa6993b959a8e6a87828ebb3c8fe5bc3ec4a2d6e65f3b8d9b4212c" ], "index": "pypi", - "version": "==2.4.0" + "version": "==3.0.2" }, "django-crispy-forms": { "hashes": [ @@ -183,82 +176,77 @@ }, "django-extensions": { "hashes": [ - "sha256:8317a3fe479b1ba3e3a04ecf33fb8d6ccf09bb18f30eab64e34c40a593741d26", - "sha256:a76a61566f1c8d96acc7bcf765080b8e91367a25a2c6f8c5bddd574493839180" + "sha256:4aafdb865104eaa5d681b9976b36c52c9d441be89b7d782e40808f1c5c0c8f93", + "sha256:8a2552fdeb222b23895ef52cdc28fc56efba976f6da07ca92937f6f5e626e345" ], "index": "pypi", - "version": "==2.1.4" + "version": "==2.2.1" }, "django-filter": { "hashes": [ - "sha256:3dafb7d2810790498895c22a1f31b2375795910680ac9c1432821cbedb1e176d", - "sha256:a3014de317bef0cd43075a0f08dfa1d319a7ccc5733c3901fb860da70b0dda68" + "sha256:558c727bce3ffa89c4a7a0b13bc8976745d63e5fd576b3a9a851650ef11c401b", + "sha256:c3deb57f0dd7ff94d7dce52a047516822013e2b441bed472b722a317658cfd14" ], "index": "pypi", - "version": "==2.1.0" + "version": "==2.2.0" }, "djangoql": { "hashes": [ - "sha256:7c488ec4e3362e5389ba3c1169d1ff9a27c4222601f32c6dbf6130ce04330d76" + "sha256:522eed3085af045242723322f67af488f44c9731d4929d579ec4198ee0076f42" ], "index": "pypi", - "version": "==0.12.3" + "version": "==0.13.0" }, "djangorestframework": { "hashes": [ - "sha256:79c6efbb2514bc50cf25906d7c0a5cfead714c7af667ff4bd110312cd380ae66", - "sha256:a4138613b67e3a223be6c97f53b13d759c5b90d2b433bad670b8ebf95402075f" + "sha256:42979bd5441bb4d8fd69d0f385024a114c3cae7df0f110600b718751250f6929", + "sha256:aedb48010ebfab9651aaab1df5fd3b4848eb4182afc909852a2110c24f89a359" ], "index": "pypi", - "version": "==3.9.1" + "version": "==3.10.2" }, "docopt": { "hashes": [ "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" ], - "index": "pypi", "version": "==0.6.2" }, "docutils": { "hashes": [ - "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", - "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", - "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", + "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", + "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99" ], - "index": "pypi", - "version": "==0.14" + "version": "==0.15.2" }, "execnet": { "hashes": [ - "sha256:a7a84d5fa07a089186a329528f127c9d73b9de57f1a1131b82bb5320ee651f6a", - "sha256:fc155a6b553c66c838d1a22dba1dc9f5f505c43285a878c6f74a79c024750b83" + "sha256:64dcdc248d007060f6f6500e7c79a4f87ee692063e3ec51e9bebf30ef2ea21d7", + "sha256:dfd10a5663f94d1235e6fbee86bc53e2f89b6f15e031e7e6d9e4bb345bcd7e52" ], - "index": "pypi", - "version": "==1.5.0" + "version": "==1.6.1" }, "factory-boy": { "hashes": [ - "sha256:6f25cc4761ac109efd503f096e2ad99421b1159f01a29dbb917359dcd68e08ca", - "sha256:d552cb872b310ae78bd7429bf318e42e1e903b1a109e899a523293dfa762ea4f" + "sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee", + "sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370" ], "index": "pypi", - "version": "==2.11.1" + "version": "==2.12.0" }, "faker": { "hashes": [ - "sha256:16342dca4d92bfc83bab6a7daf6650e0ab087605a66bc38f17523fdb01757910", - "sha256:d871ea315b2dcba9138b8344f2c131a76ac62d6227ca39f69b0c889fec97376c" + "sha256:96ad7902706f2409a2d0c3de5132f69b413555a419bacec99d3f16e657895b47", + "sha256:b3bb64aff9571510de6812df45122b633dbc6227e870edae3ed9430f94698521" ], - "index": "pypi", - "version": "==1.0.2" + "version": "==2.0.0" }, "filelock": { "hashes": [ - "sha256:b8d5ca5ca1c815e1574aee746650ea7301de63d87935b3463d26368b76e31633", - "sha256:d610c1bb404daf85976d7a82eb2ada120f04671007266b708606565dd03b5be6" + "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", + "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" ], - "index": "pypi", - "version": "==3.0.10" + "version": "==3.0.12" }, "filemagic": { "hashes": [ @@ -291,7 +279,6 @@ "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "index": "pypi", "version": "==2.8" }, "imagesize": { @@ -299,9 +286,15 @@ "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5" ], - "index": "pypi", "version": "==1.1.0" }, + "importlib-metadata": { + "hashes": [ + "sha256:23d3d873e008a513952355379d93cbcab874c58f4f034ff657c7a87422fa64e8", + "sha256:80d2de76188eabfbfcf27e6a37342c2827801e59c4cc14b0371c56fed43820e3" + ], + "version": "==0.19" + }, "inotify-simple": { "hashes": [ "sha256:fc2c10dd73278a1027d0663f2db51240af5946390f363a154361406ebdddd8dd" @@ -311,11 +304,10 @@ }, "jinja2": { "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", + "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" ], - "index": "pypi", - "version": "==2.10" + "version": "==2.10.1" }, "langdetect": { "hashes": [ @@ -326,53 +318,50 @@ }, "markupsafe": { "hashes": [ - "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", - "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", - "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", - "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", - "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", - "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", - "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", - "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", - "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", - "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", - "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", - "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", - "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", - "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", - "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", - "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", - "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", - "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", - "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", - "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", - "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", - "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", - "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", - "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", - "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", - "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", - "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", - "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" - ], - "index": "pypi", - "version": "==1.1.0" + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + ], + "version": "==1.1.1" }, "more-itertools": { "hashes": [ - "sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4", - "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", - "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9" + "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", + "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" ], - "index": "pypi", - "version": "==5.0.0" + "version": "==7.2.0" }, "packaging": { "hashes": [ - "sha256:0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af", - "sha256:9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3" + "sha256:a7ac867b97fdc07ee80a8058fe4435ccd274ecc3b0ed61d852d7d53055528cf9", + "sha256:c491ca87294da7cc01902edbe30a5bc6c4c28172b5138ab4e4aa1b9d7bfaeafe" ], - "version": "==19.0" + "version": "==19.1" }, "pdftotext": { "hashes": [ @@ -383,154 +372,126 @@ }, "pillow": { "hashes": [ - "sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e", - "sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7", - "sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a", - "sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3", - "sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1", - "sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1", - "sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7", - "sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1", - "sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3", - "sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055", - "sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf", - "sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f", - "sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f", - "sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239", - "sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe", - "sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c", - "sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697", - "sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494", - "sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356", - "sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6", - "sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000", - "sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f", - "sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c", - "sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca", - "sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8", - "sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3", - "sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad", - "sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9", - "sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc", - "sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e" - ], - "index": "pypi", - "version": "==5.4.1" + "sha256:0804f77cb1e9b6dbd37601cee11283bba39a8d44b9ddb053400c58e0c0d7d9de", + "sha256:0ab7c5b5d04691bcbd570658667dd1e21ca311c62dcfd315ad2255b1cd37f64f", + "sha256:0b3e6cf3ea1f8cecd625f1420b931c83ce74f00c29a0ff1ce4385f99900ac7c4", + "sha256:365c06a45712cd723ec16fa4ceb32ce46ad201eb7bbf6d3c16b063c72b61a3ed", + "sha256:38301fbc0af865baa4752ddae1bb3cbb24b3d8f221bf2850aad96b243306fa03", + "sha256:3aef1af1a91798536bbab35d70d35750bd2884f0832c88aeb2499aa2d1ed4992", + "sha256:3fe0ab49537d9330c9bba7f16a5f8b02da615b5c809cdf7124f356a0f182eccd", + "sha256:45a619d5c1915957449264c81c008934452e3fd3604e36809212300b2a4dab68", + "sha256:49f90f147883a0c3778fd29d3eb169d56416f25758d0f66775db9184debc8010", + "sha256:571b5a758baf1cb6a04233fb23d6cf1ca60b31f9f641b1700bfaab1194020555", + "sha256:5ac381e8b1259925287ccc5a87d9cf6322a2dc88ae28a97fe3e196385288413f", + "sha256:6153db744a743c0c8c91b8e3b9d40e0b13a5d31dbf8a12748c6d9bfd3ddc01ad", + "sha256:6fd63afd14a16f5d6b408f623cc2142917a1f92855f0df997e09a49f0341be8a", + "sha256:70acbcaba2a638923c2d337e0edea210505708d7859b87c2bd81e8f9902ae826", + "sha256:70b1594d56ed32d56ed21a7fbb2a5c6fd7446cdb7b21e749c9791eac3a64d9e4", + "sha256:76638865c83b1bb33bcac2a61ce4d13c17dba2204969dedb9ab60ef62bede686", + "sha256:7b2ec162c87fc496aa568258ac88631a2ce0acfe681a9af40842fc55deaedc99", + "sha256:7cee2cef07c8d76894ebefc54e4bb707dfc7f258ad155bd61d87f6cd487a70ff", + "sha256:7d16d4498f8b374fc625c4037742fbdd7f9ac383fd50b06f4df00c81ef60e829", + "sha256:b50bc1780681b127e28f0075dfb81d6135c3a293e0c1d0211133c75e2179b6c0", + "sha256:bd0582f831ad5bcad6ca001deba4568573a4675437db17c4031939156ff339fa", + "sha256:cfd40d8a4b59f7567620410f966bb1f32dc555b2b19f82a91b147fac296f645c", + "sha256:e3ae410089de680e8f84c68b755b42bc42c0ceb8c03dbea88a5099747091d38e", + "sha256:e9046e559c299b395b39ac7dbf16005308821c2f24a63cae2ab173bd6aa11616", + "sha256:ef6be704ae2bc8ad0ebc5cb850ee9139493b0fc4e81abcc240fb392a63ebc808", + "sha256:f8dc19d92896558f9c4317ee365729ead9d7bbcf2052a9a19a3ef17abbb8ac5b" + ], + "index": "pypi", + "version": "==6.1.0" }, "pluggy": { "hashes": [ - "sha256:8ddc32f03971bfdf900a81961a48ccf2fb677cf7715108f85295c67405798616", - "sha256:980710797ff6a041e9a73a5787804f848996ecaa6f8a1b1e08224a5894f2074a" + "sha256:0825a152ac059776623854c1543d65a4ad408eb3d33ee114dff91e57ec6ae6fc", + "sha256:b9817417e95936bf75d85d3f8767f7df6cdde751fc40aed3bb3074cbcb77757c" ], - "index": "pypi", - "version": "==0.8.1" + "version": "==0.12.0" }, "ply": { "hashes": [ "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3", "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce" ], - "index": "pypi", "version": "==3.11" }, "psycopg2": { "hashes": [ - "sha256:02445ebbb3a11a3fe8202c413d5e6faf38bb75b4e336203ee144ca2c46529f94", - "sha256:0e9873e60f98f0c52339abf8f0339d1e22bfe5aae0bcf7aabd40c055175035ec", - "sha256:1148a5eb29073280bf9057c7fc45468592c1bb75a28f6df1591adb93c8cb63d0", - "sha256:259a8324e109d4922b0fcd046e223e289830e2568d6f4132a3702439e5fd532b", - "sha256:28dffa9ed4595429e61bacac41d3f9671bb613d1442ff43bcbec63d4f73ed5e8", - "sha256:314a74302d4737a3865d40ea50e430ce1543c921ba10f39d562e807cfe2edf2a", - "sha256:36b60201b6d215d7658a71493fdf6bd5e60ad9a0cffed39906627ff9f4f3afd3", - "sha256:3f9d532bce54c4234161176ff3b8688ff337575ca441ea27597e112dfcd0ee0c", - "sha256:5d222983847b40af989ad96c07fc3f07e47925e463baa5de716be8f805b41d9b", - "sha256:6757a6d2fc58f7d8f5d471ad180a0bd7b4dd3c7d681f051504fbea7ae29c8d6f", - "sha256:6a0e0f1e74edb0ab57d89680e59e7bfefad2bfbdf7c80eb38304d897d43674bb", - "sha256:6ca703ccdf734e886a1cf53eb702261110f6a8b0ed74bcad15f1399f74d3f189", - "sha256:8513b953d8f443c446aa79a4cc8a898bd415fc5e29349054f03a7d696d495542", - "sha256:9262a5ce2038570cb81b4d6413720484cb1bc52c064b2f36228d735b1f98b794", - "sha256:97441f851d862a0c844d981cbee7ee62566c322ebb3d68f86d66aa99d483985b", - "sha256:a07feade155eb8e69b54dd6774cf6acf2d936660c61d8123b8b6b1f9247b67d6", - "sha256:a9b9c02c91b1e3ec1f1886b2d0a90a0ea07cc529cb7e6e472b556bc20ce658f3", - "sha256:ae88216f94728d691b945983140bf40d51a1ff6c7fe57def93949bf9339ed54a", - "sha256:b360ffd17659491f1a6ad7c928350e229c7b7bd83a2b922b6ee541245c7a776f", - "sha256:b4221957ceccf14b2abdabef42d806e791350be10e21b260d7c9ce49012cc19e", - "sha256:b90758e49d5e6b152a460d10b92f8a6ccf318fcc0ee814dcf53f3a6fc5328789", - "sha256:c669ea986190ed05fb289d0c100cc88064351f2b85177cbfd3564c4f4847d18c", - "sha256:d1b61999d15c79cf7f4f7cc9021477aef35277fc52452cf50fd13b713c84424d", - "sha256:de7bb043d1adaaf46e38d47e7a5f703bb3dab01376111e522b07d25e1a79c1e1", - "sha256:e393568e288d884b94d263f2669215197840d097c7e5b0acd1a51c1ea7d1aba8", - "sha256:ed7e0849337bd37d89f2c2b0216a0de863399ee5d363d31b1e5330a99044737b", - "sha256:f153f71c3164665d269a5d03c7fa76ba675c7a8de9dc09a4e2c2cdc9936a7b41", - "sha256:f1fb5a8427af099beb7f65093cbdb52e021b8e6dbdfaf020402a623f4181baf5", - "sha256:f36b333e9f86a2fba960c72b90c34be6ca71819e300f7b1fc3d2b0f0b2c546cd", - "sha256:f4526d078aedd5187d0508aa5f9a01eae6a48a470ed678406da94b4cd6524b7e" - ], - "index": "pypi", - "version": "==2.7.7" + "sha256:128d0fa910ada0157bba1cb74a9c5f92bb8a1dca77cf91a31eb274d1f889e001", + "sha256:227fd46cf9b7255f07687e5bde454d7d67ae39ca77e170097cdef8ebfc30c323", + "sha256:2315e7f104681d498ccf6fd70b0dba5bce65d60ac92171492bfe228e21dcc242", + "sha256:4b5417dcd2999db0f5a891d54717cfaee33acc64f4772c4bc574d4ff95ed9d80", + "sha256:640113ddc943522aaf71294e3f2d24013b0edd659b7820621492c9ebd3a2fb0b", + "sha256:897a6e838319b4bf648a574afb6cabcb17d0488f8c7195100d48d872419f4457", + "sha256:8dceca81409898c870e011c71179454962dec152a1a6b86a347f4be74b16d864", + "sha256:b1b8e41da09a0c3ef0b3d4bb72da0dde2abebe583c1e8462973233fd5ad0235f", + "sha256:cb407fccc12fc29dc331f2b934913405fa49b9b75af4f3a72d0f50f57ad2ca23", + "sha256:d3a27550a8185e53b244ad7e79e307594b92fede8617d80200a8cce1fba2c60f", + "sha256:f0e6b697a975d9d3ccd04135316c947dd82d841067c7800ccf622a8717e98df1" + ], + "index": "pypi", + "version": "==2.8.3" }, "py": { "hashes": [ - "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", - "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6" + "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", + "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" ], - "index": "pypi", - "version": "==1.7.0" + "version": "==1.8.0" }, "pycodestyle": { "hashes": [ - "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", - "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" ], "index": "pypi", - "version": "==2.4.0" + "version": "==2.5.0" }, "pygments": { "hashes": [ - "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", - "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d" + "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", + "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297" ], - "index": "pypi", - "version": "==2.3.1" + "version": "==2.4.2" }, "pyocr": { "hashes": [ - "sha256:b6ba6263fd92da56627dff6d263d991a2246aacd117d1788f11b93f419ca395f" + "sha256:fa15adc7e1cf0d345a2990495fe125a947c6e09a60ddba0256a1c14b2e603179" ], "index": "pypi", - "version": "==0.5.3" + "version": "==0.7.2" }, "pyparsing": { "hashes": [ - "sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a", - "sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3" + "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", + "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" ], - "index": "pypi", - "version": "==2.3.1" + "version": "==2.4.2" }, "pytest": { "hashes": [ - "sha256:41568ea7ecb4a68d7f63837cf65b92ce8d0105e43196ff2b26622995bb3dc4b2", - "sha256:c3c573a29d7c9547fb90217ece8a8843aa0c1328a797e200290dc3d0b4b823be" + "sha256:6ef6d06de77ce2961156013e9dff62f1b2688aa04d0dc244299fe7d67e09370d", + "sha256:a736fed91c12681a7b34617c8fcefe39ea04599ca72c608751c31d89579a3f77" ], "index": "pypi", - "version": "==4.1.1" + "version": "==5.0.1" }, "pytest-cov": { "hashes": [ - "sha256:0ab664b25c6aa9716cbf203b17ddb301932383046082c081b9848a0edf5add33", - "sha256:230ef817450ab0699c6cc3c9c8f7a829c34674456f2ed8df1fe1d39780f7c87f" + "sha256:2b097cde81a302e1047331b48cadacf23577e431b61e9c6f49a1170bbe3d3da6", + "sha256:e00ea4fdde970725482f1f35630d12f074e121a23801aabf2ae154ec6bdd343a" ], "index": "pypi", - "version": "==2.6.1" + "version": "==2.7.1" }, "pytest-django": { "hashes": [ - "sha256:1a5d33be930e3172fa238643a380414dc369fe8fa4b3c3de25e59ed142950736", - "sha256:e88e471d3d0f9acfb6293bb03d0ee8a33ed978734e92ea6b5312163a6c9e87cc" + "sha256:264fb4c506db5d48a6364c311a0b00b7b48a52715bad8839b2d8bee9b99ed6bb", + "sha256:4adfe5fb3ed47f0ba55506dd3daf688b1f74d5e69148c10ad2dd2f79f40c0d62" ], "index": "pypi", - "version": "==3.4.5" + "version": "==3.5.1" }, "pytest-env": { "hashes": [ @@ -541,11 +502,10 @@ }, "pytest-forked": { "hashes": [ - "sha256:260d03fbd38d5ce41a657759e8d19bc7c8cfa6d0dcfa36c0bc9742d33bc30742", - "sha256:8d05c2e6f33cd4422571b2b1bb309720c398b0549cff499e3e4cde661875ab54" + "sha256:5fe33fbd07d7b1302c95310803a5e5726a4ff7f19d5a542b7ce57c76fed8135f", + "sha256:d352aaced2ebd54d42a65825722cb433004b4446ab5d2044851d9cc7a00c9e38" ], - "index": "pypi", - "version": "==1.0.1" + "version": "==1.0.2" }, "pytest-sugar": { "hashes": [ @@ -557,27 +517,27 @@ }, "pytest-xdist": { "hashes": [ - "sha256:107e9db0ee30ead02ca93e7d6d4846675f1b2142234f0eb1cd4d76739cd9ae6f", - "sha256:5795f665e112520fa5beab736ad957e7f36ce7d44210f4004be9d99f86529d97" + "sha256:3489d91516d7847db5eaecff7a2e623dba68984835dbe6cedb05ae126c4fb17f", + "sha256:501795cb99e567746f30fe78850533d4cd500c93794128e6ab9988e92a17b1f8" ], "index": "pypi", - "version": "==1.26.0" + "version": "==1.29.0" }, "python-dateutil": { "hashes": [ - "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", - "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" + "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", + "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" ], "index": "pypi", - "version": "==2.7.5" + "version": "==2.8.0" }, "python-dotenv": { "hashes": [ - "sha256:a84569d0e00d178bc5b957f7ff208bf49287cbf61857c31c258c4a91f571527b", - "sha256:c9b1ddd3cdbe75c7d462cb84674d87130f4b948f090f02c7d7144779afb99ae0" + "sha256:debd928b49dbc2bf68040566f55cdb3252458036464806f4094487244e2a4093", + "sha256:f157d71d5fec9d4bd5f51c82746b6344dffa680ee85217c123f4a0c8117c4544" ], "index": "pypi", - "version": "==0.10.1" + "version": "==0.10.3" }, "python-gnupg": { "hashes": [ @@ -591,77 +551,106 @@ "hashes": [ "sha256:033a11de5e3d19ea25c9302d11224e1a1898fe5abd23c61c7c360c25195e3eb1" ], - "index": "pypi", "version": "==0.12.0" }, "pytz": { "hashes": [ - "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", - "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" + "sha256:26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32", + "sha256:c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7" ], "index": "pypi", - "version": "==2018.9" + "version": "==2019.2" }, "regex": { "hashes": [ - "sha256:0bcd8ab8c812278981df3161db3f94f0ec72f1fa07020173c96f20e74bd7c16a", - "sha256:20b1601b887e1073805adda2f8a09bb4c86dc7629c46c0d7bf28444dcb32920d", - "sha256:3c4327dd686d2e05b1b3d60a256fbf1c93c53001614ed8acd65453e09d40e10f", - "sha256:5e8c6cef2cd964888d5fdf16f3db3dbaaa18c5c5c648161c52c8df065cc26ac5", - "sha256:666b03b1c33ef8105f28ecf0fd26f4480931a91a6e30e29e304c1d9eddce2209", - "sha256:8afb6ecd80154464b1ad31a93228b63832526f9b0291a82a55287ae15c01de79", - "sha256:9326e1c5b9de6e74150bdd424789aecec41c7ecaf9e78bf4c3acfe6868ce1365", - "sha256:e06eac198d9c76bcbe52b987b74ead0d353cfaa9f3d8cd907ec984f4bb20ea1e", - "sha256:eee007ee39a02cb631b74f89f992766b9d7e952a750166f3e5a5baf8c328c070" + "sha256:1c70ccb8bf4ded0cbe53092e9f56dcc9d6b0efcf6e80b6ef9b0ece8a557d6635", + "sha256:2948310c01535ccb29bb600dd033b07b91f36e471953889b7f3a1e66b39d0c19", + "sha256:2ab13db0411cb308aa590d33c909ea4efeced40188d8a4a7d3d5970657fe73bc", + "sha256:38e6486c7e14683cd1b17a4218760f0ea4c015633cf1b06f7c190fb882a51ba7", + "sha256:80dde4ff10b73b823da451687363cac93dd3549e059d2dc19b72a02d048ba5aa", + "sha256:84daedefaa56320765e9c4d43912226d324ef3cc929f4d75fa95f8c579a08211", + "sha256:b98e5876ca1e63b41c4aa38d7d5cc04a736415d4e240e9ae7ebc4f780083c7d5", + "sha256:ca4f47131af28ef168ff7c80d4b4cad019cb4cabb5fa26143f43aa3dbd60389c", + "sha256:cf7838110d3052d359da527372666429b9485ab739286aa1a11ed482f037a88c", + "sha256:dd4e8924915fa748e128864352875d3d0be5f4597ab1b1d475988b8e3da10dd7", + "sha256:f2c65530255e4010a5029eb11138f5ecd5aa70363f57a3444d83b3253b0891be" ], - "index": "pypi", - "version": "==2019.1.24" + "version": "==2019.6.8" }, "requests": { "hashes": [ - "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", - "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" ], - "index": "pypi", - "version": "==2.21.0" + "version": "==2.22.0" }, "six": { "hashes": [ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], - "index": "pypi", "version": "==1.12.0" }, "snowballstemmer": { "hashes": [ - "sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", - "sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89" + "sha256:9f3b9ffe0809d174f7047e121431acf99c89a7040f0ca84f94ba53a498e6d0c9" ], - "index": "pypi", - "version": "==1.2.1" + "version": "==1.9.0" }, "sphinx": { "hashes": [ - "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5", - "sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8" + "sha256:22538e1bbe62b407cf5a8aabe1bb15848aa66bb79559f42f5202bbce6b757a69", + "sha256:f9a79e746b87921cabc3baa375199c6076d1270cee53915dbd24fdbeaaacc427" ], "index": "pypi", - "version": "==1.8.3" + "version": "==2.1.2" }, - "sphinxcontrib-websupport": { + "sphinxcontrib-applehelp": { "hashes": [ - "sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", - "sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" + "sha256:edaa0ab2b2bc74403149cb0209d6775c96de797dfd5b5e2a71981309efab3897", + "sha256:fb8dee85af95e5c30c91f10e7eb3c8967308518e0f7488a2828ef7bc191d0d5d" ], - "index": "pypi", - "version": "==1.1.0" + "version": "==1.0.1" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:6c64b077937330a9128a4da74586e8c2130262f014689b4b89e2d08ee7294a34", + "sha256:9512ecb00a2b0821a146736b39f7aeb90759834b07e81e8cc23a9c70bacb9981" + ], + "version": "==1.0.1" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422", + "sha256:d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7" + ], + "version": "==1.0.2" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:513049b93031beb1f57d4daea74068a4feb77aa5630f856fcff2e50de14e9a20", + "sha256:79465ce11ae5694ff165becda529a600c754f4bc459778778c7017374d4d406f" + ], + "version": "==1.0.2" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227", + "sha256:db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768" + ], + "version": "==1.1.3" }, "termcolor": { "hashes": [ "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b" ], - "index": "pypi", "version": "==1.1.0" }, "text-unidecode": { @@ -669,7 +658,6 @@ "sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d", "sha256:801e38bd550b943563660a91de8d4b6fa5df60a542be9093f7abf819f86050cc" ], - "index": "pypi", "version": "==1.2" }, "toml": { @@ -677,39 +665,43 @@ "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" ], - "index": "pypi", "version": "==0.10.0" }, "tox": { "hashes": [ - "sha256:04f8f1aa05de8e76d7a266ccd14e0d665d429977cd42123bc38efa9b59964e9e", - "sha256:25ef928babe88c71e3ed3af0c464d1160b01fca2dd1870a5bb26c2dea61a17fc" + "sha256:dab0b0160dd187b654fc33d690ee1d7bf328bd5b8dc6ef3bb3cc468969c659ba", + "sha256:ee35ffce74933a6c6ac10c9a0182e41763140a5a5070e21b114feca56eaccdcd" ], "index": "pypi", - "version": "==3.7.0" + "version": "==3.13.2" }, "tzlocal": { "hashes": [ - "sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e" + "sha256:11c9f16e0a633b4b60e1eede97d8a46340d042e67b670b290ca526576e039048", + "sha256:949b9dd5ba4be17190a80c0268167d7e6c92c62b30026cf9764caf3e308e5590" ], - "index": "pypi", - "version": "==1.5.1" + "version": "==2.0.0" }, "urllib3": { "hashes": [ - "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", - "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" + "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", + "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" ], - "index": "pypi", - "version": "==1.24.1" + "version": "==1.25.3" }, "virtualenv": { "hashes": [ - "sha256:58c359370401e0af817fb0070911e599c5fdc836166306b04fd0f278151ed125", - "sha256:729f0bcab430e4ef137646805b5b1d8efbb43fe53d4a0f33328624a84a5121f7" + "sha256:6cb2e4c18d22dbbe283d0a0c31bb7d90771a606b2cb3415323eea008eaee6a9d", + "sha256:909fe0d3f7c9151b2df0a2cb53e55bdb7b0d61469353ff7a49fd47b0f0ab9285" ], - "index": "pypi", - "version": "==16.3.0" + "version": "==16.7.2" + }, + "wcwidth": { + "hashes": [ + "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", + "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + ], + "version": "==0.1.7" }, "whitenoise": { "hashes": [ @@ -718,6 +710,13 @@ ], "index": "pypi", "version": "==4.1.3" + }, + "zipp": { + "hashes": [ + "sha256:4970c3758f4e89a7857a973b1e2a5d75bcdc47794442f2e2dd4fe8e0466e809a", + "sha256:8a5712cfd3bb4248015eb3b0b3c54a5f6ee3f2425963ef2a0125b8bc40aafaec" + ], + "version": "==0.5.2" } }, "develop": { @@ -737,11 +736,11 @@ }, "ipython": { "hashes": [ - "sha256:11067ab11d98b1e6c7f0993506f7a5f8a91af420f7e82be6575fcb7a6ca372a0", - "sha256:60bc55c2c1d287161191cc2469e73c116d9b634cff25fe214a43cba7cec94c79" + "sha256:1d3a1692921e932751bc1a1f7bb96dc38671eeefdc66ed33ee4cbc57e92a410e", + "sha256:537cd0176ff6abd06ef3e23f2d0c4c2c8a4d9277b7451544c6cbf56d1c79a83d" ], "index": "pypi", - "version": "==7.6.1" + "version": "==7.7.0" }, "ipython-genutils": { "hashes": [ @@ -796,18 +795,16 @@ }, "pygments": { "hashes": [ - "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", - "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d" + "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", + "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297" ], - "index": "pypi", - "version": "==2.3.1" + "version": "==2.4.2" }, "six": { "hashes": [ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" ], - "index": "pypi", "version": "==1.12.0" }, "traitlets": { diff --git a/requirements.txt b/requirements.txt old mode 100755 new mode 100644 index a643a88cf..406fcb3bc --- a/requirements.txt +++ b/requirements.txt @@ -1,72 +1,80 @@ -i https://pypi.python.org/simple alabaster==0.7.12 apipkg==1.5 -atomicwrites==1.2.1 -attrs==18.2.0 -babel==2.6.0 +atomicwrites==1.3.0 +attrs==19.1.0 +babel==2.7.0 brotli==1.0.7 -certifi==2018.11.29 +certifi==2019.6.16 chardet==3.0.4 -coverage==4.5.2 -coveralls==1.5.1 -dateparser==0.7.0 -django-cors-headers==2.4.0 +coverage==4.5.4 +coveralls==1.8.2 +dateparser==0.7.1 +django-cors-headers==3.0.2 django-crispy-forms==1.7.2 -django-extensions==2.1.4 -django-filter==2.1.0 -django==2.0.10 -djangoql==0.12.3 -djangorestframework==3.9.1 +django-extensions==2.2.1 +django-filter==2.2.0 +django==2.0.13 +djangoql==0.13.0 +djangorestframework==3.10.2 docopt==0.6.2 -docutils==0.14 -execnet==1.5.0 -factory-boy==2.11.1 -faker==1.0.2 -filelock==3.0.10 +docutils==0.15.2 +execnet==1.6.1 +factory-boy==2.12.0 +faker==2.0.0 +filelock==3.0.12 filemagic==1.6 fuzzywuzzy[speedup]==0.15.0 gunicorn==19.9.0 idna==2.8 imagesize==1.1.0 +importlib-metadata==0.19 inotify-simple==1.1.8; sys_platform == 'linux' -jinja2==2.10 +jinja2==2.10.1 langdetect==1.0.7 -markupsafe==1.1.0 -more-itertools==5.0.0 -packaging==19.0 +markupsafe==1.1.1 +more-itertools==7.2.0 +packaging==19.1 pdftotext==2.1.1 -pillow==5.4.1 -pluggy==0.8.1 +pillow==6.1.0 +pluggy==0.12.0 ply==3.11 -psycopg2==2.7.7 -py==1.7.0 -pycodestyle==2.4.0 -pygments==2.3.1 -pyocr==0.5.3 -pyparsing==2.3.1 -pytest-cov==2.6.1 -pytest-django==3.4.5 +psycopg2==2.8.3 +py==1.8.0 +pycodestyle==2.5.0 +pygments==2.4.2 +pyocr==0.7.2 +pyparsing==2.4.2 +pytest-cov==2.7.1 +pytest-django==3.5.1 pytest-env==0.6.2 -pytest-forked==1.0.1 +pytest-forked==1.0.2 pytest-sugar==0.9.2 -pytest-xdist==1.26.0 -pytest==4.1.1 -python-dateutil==2.7.5 -python-dotenv==0.10.1 +pytest-xdist==1.29.0 +pytest==5.0.1 +python-dateutil==2.8.0 +python-dotenv==0.10.3 python-gnupg==0.4.4 python-levenshtein==0.12.0 -pytz==2018.9 -regex==2019.1.24 -requests==2.21.0 +pytz==2019.2 +regex==2019.6.8 +requests==2.22.0 six==1.12.0 -snowballstemmer==1.2.1 -sphinx==1.8.3 -sphinxcontrib-websupport==1.1.0 +snowballstemmer==1.9.0 +sphinx==2.1.2 +sphinxcontrib-applehelp==1.0.1 +sphinxcontrib-devhelp==1.0.1 +sphinxcontrib-htmlhelp==1.0.2 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.2 +sphinxcontrib-serializinghtml==1.1.3 termcolor==1.1.0 text-unidecode==1.2 toml==0.10.0 -tox==3.7.0 -tzlocal==1.5.1 -urllib3==1.24.1 -virtualenv==16.3.0 +tox==3.13.2 +tzlocal==2.0.0 +urllib3==1.25.3 +virtualenv==16.7.2 +wcwidth==0.1.7 whitenoise==4.1.3 +zipp==0.5.2 From 2efd278ee9dc0f4e9ec63999865aa138b8fc2f12 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Tue, 6 Aug 2019 12:26:14 -0900 Subject: [PATCH 023/101] Add http to cors origin whitelist as this is required with new version --- src/paperless/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/paperless/settings.py b/src/paperless/settings.py index ce387be07..ffd5c0d6e 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -107,7 +107,7 @@ def __get_boolean(key, default="NO"): STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' # We allow CORS from localhost:8080 -CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "localhost:8080").split(",")) +CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "http://localhost:8080").split(",")) # If auth is disabled, we just use our "bypass" authentication middleware if bool(os.getenv("PAPERLESS_DISABLE_LOGIN", "false").lower() in ("yes", "y", "1", "t", "true")): From 30b18df71cd118db2dd1f7d8faf49c63a021b296 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Wed, 7 Aug 2019 21:38:54 +0200 Subject: [PATCH 024/101] Adjust requirements --- Pipfile.lock | 231 +++++++++++++++++++++----------------- requirements.txt | 46 ++++---- src/paperless/settings.py | 2 +- 3 files changed, 151 insertions(+), 128 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 249d3ff6e..b1ec809e4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -136,35 +136,35 @@ }, "coveralls": { "hashes": [ - "sha256:9bc5a1f92682eef59f688a8f280207190d9a6afb84cef8f567fa47631a784060", - "sha256:fb51cddef4bc458de347274116df15d641a735d3f0a580a9472174e2e62f408c" + "sha256:ab638e88d38916a6cedbf80a9cd8992d5fa55c77ab755e262e00b36792b7cd6d", + "sha256:b2388747e2529fa4c669fb1e3e2756e4e07b6ee56c7d9fce05f35ccccc913aa0" ], "index": "pypi", - "version": "==1.8.2" + "version": "==1.5.1" }, "dateparser": { "hashes": [ - "sha256:42d51be54e74a8e80a4d76d1fa6e4edd997098fce24ad2d94a2eab5ef247193e", - "sha256:78124c458c461ea7198faa3c038f6381f37588b84bb42740e91a4cbd260b1d09" + "sha256:940828183c937bcec530753211b70f673c0a9aab831e43273489b310538dff86", + "sha256:b452ef8b36cd78ae86a50721794bc674aa3994e19b570f7ba92810f4e0a2ae03" ], "index": "pypi", - "version": "==0.7.1" + "version": "==0.7.0" }, "django": { "hashes": [ - "sha256:665457d4146bbd34ae9d2970fa3b37082d7b225b0671bfd24c337458f229db78", - "sha256:bde46d4dbc410678e89bc95ea5d312dd6eb4c37d0fa0e19c9415cad94addf22f" + "sha256:0292a7ad7d8ffc9cfc6a77f043d2e81f5bbc360c0c4a1686e130ef3432437d23", + "sha256:e89f613e3c1f7ff245ffee3560472f9fa9c07060b11f65e1de3cb763f8dcd4b9" ], "index": "pypi", - "version": "==2.0.13" + "version": "==2.0.10" }, "django-cors-headers": { "hashes": [ - "sha256:5b80bf0f8d7fc6e2bcb4f40781d5ff3661961bbf1982e52daec77241dea3b890", - "sha256:ebf3e2cf25aa6993b959a8e6a87828ebb3c8fe5bc3ec4a2d6e65f3b8d9b4212c" + "sha256:5545009c9b233ea7e70da7dbab7cb1c12afa01279895086f98ec243d7eab46fa", + "sha256:c4c2ee97139d18541a1be7d96fe337d1694623816d83f53cb7c00da9b94acae1" ], "index": "pypi", - "version": "==3.0.2" + "version": "==2.4.0" }, "django-crispy-forms": { "hashes": [ @@ -176,34 +176,34 @@ }, "django-extensions": { "hashes": [ - "sha256:4aafdb865104eaa5d681b9976b36c52c9d441be89b7d782e40808f1c5c0c8f93", - "sha256:8a2552fdeb222b23895ef52cdc28fc56efba976f6da07ca92937f6f5e626e345" + "sha256:8317a3fe479b1ba3e3a04ecf33fb8d6ccf09bb18f30eab64e34c40a593741d26", + "sha256:a76a61566f1c8d96acc7bcf765080b8e91367a25a2c6f8c5bddd574493839180" ], "index": "pypi", - "version": "==2.2.1" + "version": "==2.1.4" }, "django-filter": { "hashes": [ - "sha256:558c727bce3ffa89c4a7a0b13bc8976745d63e5fd576b3a9a851650ef11c401b", - "sha256:c3deb57f0dd7ff94d7dce52a047516822013e2b441bed472b722a317658cfd14" + "sha256:3dafb7d2810790498895c22a1f31b2375795910680ac9c1432821cbedb1e176d", + "sha256:a3014de317bef0cd43075a0f08dfa1d319a7ccc5733c3901fb860da70b0dda68" ], "index": "pypi", - "version": "==2.2.0" + "version": "==2.1.0" }, "djangoql": { "hashes": [ - "sha256:522eed3085af045242723322f67af488f44c9731d4929d579ec4198ee0076f42" + "sha256:7c488ec4e3362e5389ba3c1169d1ff9a27c4222601f32c6dbf6130ce04330d76" ], "index": "pypi", - "version": "==0.13.0" + "version": "==0.12.3" }, "djangorestframework": { "hashes": [ - "sha256:42979bd5441bb4d8fd69d0f385024a114c3cae7df0f110600b718751250f6929", - "sha256:aedb48010ebfab9651aaab1df5fd3b4848eb4182afc909852a2110c24f89a359" + "sha256:79c6efbb2514bc50cf25906d7c0a5cfead714c7af667ff4bd110312cd380ae66", + "sha256:a4138613b67e3a223be6c97f53b13d759c5b90d2b433bad670b8ebf95402075f" ], "index": "pypi", - "version": "==3.10.2" + "version": "==3.9.1" }, "docopt": { "hashes": [ @@ -228,11 +228,11 @@ }, "factory-boy": { "hashes": [ - "sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee", - "sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370" + "sha256:6f25cc4761ac109efd503f096e2ad99421b1159f01a29dbb917359dcd68e08ca", + "sha256:d552cb872b310ae78bd7429bf318e42e1e903b1a109e899a523293dfa762ea4f" ], "index": "pypi", - "version": "==2.12.0" + "version": "==2.11.1" }, "faker": { "hashes": [ @@ -372,35 +372,39 @@ }, "pillow": { "hashes": [ - "sha256:0804f77cb1e9b6dbd37601cee11283bba39a8d44b9ddb053400c58e0c0d7d9de", - "sha256:0ab7c5b5d04691bcbd570658667dd1e21ca311c62dcfd315ad2255b1cd37f64f", - "sha256:0b3e6cf3ea1f8cecd625f1420b931c83ce74f00c29a0ff1ce4385f99900ac7c4", - "sha256:365c06a45712cd723ec16fa4ceb32ce46ad201eb7bbf6d3c16b063c72b61a3ed", - "sha256:38301fbc0af865baa4752ddae1bb3cbb24b3d8f221bf2850aad96b243306fa03", - "sha256:3aef1af1a91798536bbab35d70d35750bd2884f0832c88aeb2499aa2d1ed4992", - "sha256:3fe0ab49537d9330c9bba7f16a5f8b02da615b5c809cdf7124f356a0f182eccd", - "sha256:45a619d5c1915957449264c81c008934452e3fd3604e36809212300b2a4dab68", - "sha256:49f90f147883a0c3778fd29d3eb169d56416f25758d0f66775db9184debc8010", - "sha256:571b5a758baf1cb6a04233fb23d6cf1ca60b31f9f641b1700bfaab1194020555", - "sha256:5ac381e8b1259925287ccc5a87d9cf6322a2dc88ae28a97fe3e196385288413f", - "sha256:6153db744a743c0c8c91b8e3b9d40e0b13a5d31dbf8a12748c6d9bfd3ddc01ad", - "sha256:6fd63afd14a16f5d6b408f623cc2142917a1f92855f0df997e09a49f0341be8a", - "sha256:70acbcaba2a638923c2d337e0edea210505708d7859b87c2bd81e8f9902ae826", - "sha256:70b1594d56ed32d56ed21a7fbb2a5c6fd7446cdb7b21e749c9791eac3a64d9e4", - "sha256:76638865c83b1bb33bcac2a61ce4d13c17dba2204969dedb9ab60ef62bede686", - "sha256:7b2ec162c87fc496aa568258ac88631a2ce0acfe681a9af40842fc55deaedc99", - "sha256:7cee2cef07c8d76894ebefc54e4bb707dfc7f258ad155bd61d87f6cd487a70ff", - "sha256:7d16d4498f8b374fc625c4037742fbdd7f9ac383fd50b06f4df00c81ef60e829", - "sha256:b50bc1780681b127e28f0075dfb81d6135c3a293e0c1d0211133c75e2179b6c0", - "sha256:bd0582f831ad5bcad6ca001deba4568573a4675437db17c4031939156ff339fa", - "sha256:cfd40d8a4b59f7567620410f966bb1f32dc555b2b19f82a91b147fac296f645c", - "sha256:e3ae410089de680e8f84c68b755b42bc42c0ceb8c03dbea88a5099747091d38e", - "sha256:e9046e559c299b395b39ac7dbf16005308821c2f24a63cae2ab173bd6aa11616", - "sha256:ef6be704ae2bc8ad0ebc5cb850ee9139493b0fc4e81abcc240fb392a63ebc808", - "sha256:f8dc19d92896558f9c4317ee365729ead9d7bbcf2052a9a19a3ef17abbb8ac5b" - ], - "index": "pypi", - "version": "==6.1.0" + "sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e", + "sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7", + "sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a", + "sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3", + "sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1", + "sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1", + "sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7", + "sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1", + "sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3", + "sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055", + "sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf", + "sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f", + "sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f", + "sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239", + "sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe", + "sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c", + "sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697", + "sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494", + "sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356", + "sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6", + "sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000", + "sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f", + "sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c", + "sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca", + "sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8", + "sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3", + "sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad", + "sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9", + "sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc", + "sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e" + ], + "index": "pypi", + "version": "==5.4.1" }, "pluggy": { "hashes": [ @@ -418,20 +422,39 @@ }, "psycopg2": { "hashes": [ - "sha256:128d0fa910ada0157bba1cb74a9c5f92bb8a1dca77cf91a31eb274d1f889e001", - "sha256:227fd46cf9b7255f07687e5bde454d7d67ae39ca77e170097cdef8ebfc30c323", - "sha256:2315e7f104681d498ccf6fd70b0dba5bce65d60ac92171492bfe228e21dcc242", - "sha256:4b5417dcd2999db0f5a891d54717cfaee33acc64f4772c4bc574d4ff95ed9d80", - "sha256:640113ddc943522aaf71294e3f2d24013b0edd659b7820621492c9ebd3a2fb0b", - "sha256:897a6e838319b4bf648a574afb6cabcb17d0488f8c7195100d48d872419f4457", - "sha256:8dceca81409898c870e011c71179454962dec152a1a6b86a347f4be74b16d864", - "sha256:b1b8e41da09a0c3ef0b3d4bb72da0dde2abebe583c1e8462973233fd5ad0235f", - "sha256:cb407fccc12fc29dc331f2b934913405fa49b9b75af4f3a72d0f50f57ad2ca23", - "sha256:d3a27550a8185e53b244ad7e79e307594b92fede8617d80200a8cce1fba2c60f", - "sha256:f0e6b697a975d9d3ccd04135316c947dd82d841067c7800ccf622a8717e98df1" - ], - "index": "pypi", - "version": "==2.8.3" + "sha256:02445ebbb3a11a3fe8202c413d5e6faf38bb75b4e336203ee144ca2c46529f94", + "sha256:0e9873e60f98f0c52339abf8f0339d1e22bfe5aae0bcf7aabd40c055175035ec", + "sha256:1148a5eb29073280bf9057c7fc45468592c1bb75a28f6df1591adb93c8cb63d0", + "sha256:259a8324e109d4922b0fcd046e223e289830e2568d6f4132a3702439e5fd532b", + "sha256:28dffa9ed4595429e61bacac41d3f9671bb613d1442ff43bcbec63d4f73ed5e8", + "sha256:314a74302d4737a3865d40ea50e430ce1543c921ba10f39d562e807cfe2edf2a", + "sha256:36b60201b6d215d7658a71493fdf6bd5e60ad9a0cffed39906627ff9f4f3afd3", + "sha256:3f9d532bce54c4234161176ff3b8688ff337575ca441ea27597e112dfcd0ee0c", + "sha256:5d222983847b40af989ad96c07fc3f07e47925e463baa5de716be8f805b41d9b", + "sha256:6757a6d2fc58f7d8f5d471ad180a0bd7b4dd3c7d681f051504fbea7ae29c8d6f", + "sha256:6a0e0f1e74edb0ab57d89680e59e7bfefad2bfbdf7c80eb38304d897d43674bb", + "sha256:6ca703ccdf734e886a1cf53eb702261110f6a8b0ed74bcad15f1399f74d3f189", + "sha256:8513b953d8f443c446aa79a4cc8a898bd415fc5e29349054f03a7d696d495542", + "sha256:9262a5ce2038570cb81b4d6413720484cb1bc52c064b2f36228d735b1f98b794", + "sha256:97441f851d862a0c844d981cbee7ee62566c322ebb3d68f86d66aa99d483985b", + "sha256:a07feade155eb8e69b54dd6774cf6acf2d936660c61d8123b8b6b1f9247b67d6", + "sha256:a9b9c02c91b1e3ec1f1886b2d0a90a0ea07cc529cb7e6e472b556bc20ce658f3", + "sha256:ae88216f94728d691b945983140bf40d51a1ff6c7fe57def93949bf9339ed54a", + "sha256:b360ffd17659491f1a6ad7c928350e229c7b7bd83a2b922b6ee541245c7a776f", + "sha256:b4221957ceccf14b2abdabef42d806e791350be10e21b260d7c9ce49012cc19e", + "sha256:b90758e49d5e6b152a460d10b92f8a6ccf318fcc0ee814dcf53f3a6fc5328789", + "sha256:c669ea986190ed05fb289d0c100cc88064351f2b85177cbfd3564c4f4847d18c", + "sha256:d1b61999d15c79cf7f4f7cc9021477aef35277fc52452cf50fd13b713c84424d", + "sha256:de7bb043d1adaaf46e38d47e7a5f703bb3dab01376111e522b07d25e1a79c1e1", + "sha256:e393568e288d884b94d263f2669215197840d097c7e5b0acd1a51c1ea7d1aba8", + "sha256:ed7e0849337bd37d89f2c2b0216a0de863399ee5d363d31b1e5330a99044737b", + "sha256:f153f71c3164665d269a5d03c7fa76ba675c7a8de9dc09a4e2c2cdc9936a7b41", + "sha256:f1fb5a8427af099beb7f65093cbdb52e021b8e6dbdfaf020402a623f4181baf5", + "sha256:f36b333e9f86a2fba960c72b90c34be6ca71819e300f7b1fc3d2b0f0b2c546cd", + "sha256:f4526d078aedd5187d0508aa5f9a01eae6a48a470ed678406da94b4cd6524b7e" + ], + "index": "pypi", + "version": "==2.7.7" }, "py": { "hashes": [ @@ -442,11 +465,11 @@ }, "pycodestyle": { "hashes": [ - "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", - "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", + "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" ], "index": "pypi", - "version": "==2.5.0" + "version": "==2.4.0" }, "pygments": { "hashes": [ @@ -457,10 +480,10 @@ }, "pyocr": { "hashes": [ - "sha256:fa15adc7e1cf0d345a2990495fe125a947c6e09a60ddba0256a1c14b2e603179" + "sha256:b6ba6263fd92da56627dff6d263d991a2246aacd117d1788f11b93f419ca395f" ], "index": "pypi", - "version": "==0.7.2" + "version": "==0.5.3" }, "pyparsing": { "hashes": [ @@ -471,27 +494,27 @@ }, "pytest": { "hashes": [ - "sha256:6ef6d06de77ce2961156013e9dff62f1b2688aa04d0dc244299fe7d67e09370d", - "sha256:a736fed91c12681a7b34617c8fcefe39ea04599ca72c608751c31d89579a3f77" + "sha256:41568ea7ecb4a68d7f63837cf65b92ce8d0105e43196ff2b26622995bb3dc4b2", + "sha256:c3c573a29d7c9547fb90217ece8a8843aa0c1328a797e200290dc3d0b4b823be" ], "index": "pypi", - "version": "==5.0.1" + "version": "==4.1.1" }, "pytest-cov": { "hashes": [ - "sha256:2b097cde81a302e1047331b48cadacf23577e431b61e9c6f49a1170bbe3d3da6", - "sha256:e00ea4fdde970725482f1f35630d12f074e121a23801aabf2ae154ec6bdd343a" + "sha256:0ab664b25c6aa9716cbf203b17ddb301932383046082c081b9848a0edf5add33", + "sha256:230ef817450ab0699c6cc3c9c8f7a829c34674456f2ed8df1fe1d39780f7c87f" ], "index": "pypi", - "version": "==2.7.1" + "version": "==2.6.1" }, "pytest-django": { "hashes": [ - "sha256:264fb4c506db5d48a6364c311a0b00b7b48a52715bad8839b2d8bee9b99ed6bb", - "sha256:4adfe5fb3ed47f0ba55506dd3daf688b1f74d5e69148c10ad2dd2f79f40c0d62" + "sha256:1a5d33be930e3172fa238643a380414dc369fe8fa4b3c3de25e59ed142950736", + "sha256:e88e471d3d0f9acfb6293bb03d0ee8a33ed978734e92ea6b5312163a6c9e87cc" ], "index": "pypi", - "version": "==3.5.1" + "version": "==3.4.5" }, "pytest-env": { "hashes": [ @@ -517,27 +540,27 @@ }, "pytest-xdist": { "hashes": [ - "sha256:3489d91516d7847db5eaecff7a2e623dba68984835dbe6cedb05ae126c4fb17f", - "sha256:501795cb99e567746f30fe78850533d4cd500c93794128e6ab9988e92a17b1f8" + "sha256:107e9db0ee30ead02ca93e7d6d4846675f1b2142234f0eb1cd4d76739cd9ae6f", + "sha256:5795f665e112520fa5beab736ad957e7f36ce7d44210f4004be9d99f86529d97" ], "index": "pypi", - "version": "==1.29.0" + "version": "==1.26.0" }, "python-dateutil": { "hashes": [ - "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", - "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" + "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", + "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" ], "index": "pypi", - "version": "==2.8.0" + "version": "==2.7.5" }, "python-dotenv": { "hashes": [ - "sha256:debd928b49dbc2bf68040566f55cdb3252458036464806f4094487244e2a4093", - "sha256:f157d71d5fec9d4bd5f51c82746b6344dffa680ee85217c123f4a0c8117c4544" + "sha256:a84569d0e00d178bc5b957f7ff208bf49287cbf61857c31c258c4a91f571527b", + "sha256:c9b1ddd3cdbe75c7d462cb84674d87130f4b948f090f02c7d7144779afb99ae0" ], "index": "pypi", - "version": "==0.10.3" + "version": "==0.10.1" }, "python-gnupg": { "hashes": [ @@ -555,11 +578,11 @@ }, "pytz": { "hashes": [ - "sha256:26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32", - "sha256:c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7" + "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", + "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" ], "index": "pypi", - "version": "==2019.2" + "version": "==2018.9" }, "regex": { "hashes": [ @@ -599,11 +622,11 @@ }, "sphinx": { "hashes": [ - "sha256:22538e1bbe62b407cf5a8aabe1bb15848aa66bb79559f42f5202bbce6b757a69", - "sha256:f9a79e746b87921cabc3baa375199c6076d1270cee53915dbd24fdbeaaacc427" + "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5", + "sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8" ], "index": "pypi", - "version": "==2.1.2" + "version": "==1.8.3" }, "sphinxcontrib-applehelp": { "hashes": [ @@ -669,11 +692,11 @@ }, "tox": { "hashes": [ - "sha256:dab0b0160dd187b654fc33d690ee1d7bf328bd5b8dc6ef3bb3cc468969c659ba", - "sha256:ee35ffce74933a6c6ac10c9a0182e41763140a5a5070e21b114feca56eaccdcd" + "sha256:04f8f1aa05de8e76d7a266ccd14e0d665d429977cd42123bc38efa9b59964e9e", + "sha256:25ef928babe88c71e3ed3af0c464d1160b01fca2dd1870a5bb26c2dea61a17fc" ], "index": "pypi", - "version": "==3.13.2" + "version": "==3.7.0" }, "tzlocal": { "hashes": [ @@ -736,11 +759,11 @@ }, "ipython": { "hashes": [ - "sha256:1d3a1692921e932751bc1a1f7bb96dc38671eeefdc66ed33ee4cbc57e92a410e", - "sha256:537cd0176ff6abd06ef3e23f2d0c4c2c8a4d9277b7451544c6cbf56d1c79a83d" + "sha256:6a9496209b76463f1dec126ab928919aaf1f55b38beb9219af3fe202f6bbdd12", + "sha256:f69932b1e806b38a7818d9a1e918e5821b685715040b48e59c657b3c7961b742" ], "index": "pypi", - "version": "==7.7.0" + "version": "==7.2.0" }, "ipython-genutils": { "hashes": [ diff --git a/requirements.txt b/requirements.txt index 406fcb3bc..0157b9184 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,19 +8,19 @@ brotli==1.0.7 certifi==2019.6.16 chardet==3.0.4 coverage==4.5.4 -coveralls==1.8.2 -dateparser==0.7.1 -django-cors-headers==3.0.2 +coveralls==1.5.1 +dateparser==0.7.0 +django-cors-headers==2.4.0 django-crispy-forms==1.7.2 -django-extensions==2.2.1 -django-filter==2.2.0 -django==2.0.13 -djangoql==0.13.0 -djangorestframework==3.10.2 +django-extensions==2.1.4 +django-filter==2.1.0 +django==2.0.10 +djangoql==0.12.3 +djangorestframework==3.9.1 docopt==0.6.2 docutils==0.15.2 execnet==1.6.1 -factory-boy==2.12.0 +factory-boy==2.11.1 faker==2.0.0 filelock==3.0.12 filemagic==1.6 @@ -29,39 +29,39 @@ gunicorn==19.9.0 idna==2.8 imagesize==1.1.0 importlib-metadata==0.19 -inotify-simple==1.1.8; sys_platform == 'linux' +inotify-simple==1.1.8 jinja2==2.10.1 langdetect==1.0.7 markupsafe==1.1.1 more-itertools==7.2.0 packaging==19.1 pdftotext==2.1.1 -pillow==6.1.0 +pillow==5.4.1 pluggy==0.12.0 ply==3.11 -psycopg2==2.8.3 +psycopg2==2.7.7 py==1.8.0 -pycodestyle==2.5.0 +pycodestyle==2.4.0 pygments==2.4.2 -pyocr==0.7.2 +pyocr==0.5.3 pyparsing==2.4.2 -pytest-cov==2.7.1 -pytest-django==3.5.1 +pytest-cov==2.6.1 +pytest-django==3.4.5 pytest-env==0.6.2 pytest-forked==1.0.2 pytest-sugar==0.9.2 -pytest-xdist==1.29.0 -pytest==5.0.1 -python-dateutil==2.8.0 -python-dotenv==0.10.3 +pytest-xdist==1.26.0 +pytest==4.1.1 +python-dateutil==2.7.5 +python-dotenv==0.10.1 python-gnupg==0.4.4 python-levenshtein==0.12.0 -pytz==2019.2 +pytz==2018.9 regex==2019.6.8 requests==2.22.0 six==1.12.0 snowballstemmer==1.9.0 -sphinx==2.1.2 +sphinx==1.8.3 sphinxcontrib-applehelp==1.0.1 sphinxcontrib-devhelp==1.0.1 sphinxcontrib-htmlhelp==1.0.2 @@ -71,7 +71,7 @@ sphinxcontrib-serializinghtml==1.1.3 termcolor==1.1.0 text-unidecode==1.2 toml==0.10.0 -tox==3.13.2 +tox==3.7.0 tzlocal==2.0.0 urllib3==1.25.3 virtualenv==16.7.2 diff --git a/src/paperless/settings.py b/src/paperless/settings.py index ffd5c0d6e..ce387be07 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -107,7 +107,7 @@ def __get_boolean(key, default="NO"): STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' # We allow CORS from localhost:8080 -CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "http://localhost:8080").split(",")) +CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "localhost:8080").split(",")) # If auth is disabled, we just use our "bypass" authentication middleware if bool(os.getenv("PAPERLESS_DISABLE_LOGIN", "false").lower() in ("yes", "y", "1", "t", "true")): From 5ae3433a6d869c53d03b9551ef647c06c1c47949 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Thu, 8 Aug 2019 01:00:28 +0200 Subject: [PATCH 025/101] Specify sys platform for inotify --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0157b9184..20ba52c5b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,7 +29,7 @@ gunicorn==19.9.0 idna==2.8 imagesize==1.1.0 importlib-metadata==0.19 -inotify-simple==1.1.8 +inotify-simple==1.1.8; sys_platform == 'linux' jinja2==2.10.1 langdetect==1.0.7 markupsafe==1.1.1 From dfe5f25f0134361227d03e02d178d81414027319 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Thu, 8 Aug 2019 01:01:53 +0200 Subject: [PATCH 026/101] Remove python 3.4 from travis as it has reached end-of-life and does not support a lot of the dependencies newer versions --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8773c486c..fa1785d8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,7 @@ before_install: sudo: false matrix: - include: - - python: "3.4" + include: - python: "3.5" - python: "3.6" - python: "3.7-dev" From 82855f9d439b7712b8a65c8bac680bc10fc1f92d Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Sat, 10 Aug 2019 17:25:52 +0200 Subject: [PATCH 027/101] Adjust path in setup docs to python 3.6 as 3.4 is deprecated --- docs/setup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/setup.rst b/docs/setup.rst index da17c38e8..6a151052e 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -327,7 +327,7 @@ and mod_wsgi, with a Paperless installation in ``/home/paperless/``: WSGIScriptAlias / /home/paperless/paperless/src/paperless/wsgi.py - WSGIDaemonProcess example.com user=paperless group=paperless threads=5 python-path=/home/paperless/paperless/src:/home/paperless/.env/lib/python3.4/site-packages + WSGIDaemonProcess example.com user=paperless group=paperless threads=5 python-path=/home/paperless/paperless/src:/home/paperless/.env/lib/python3.6/site-packages WSGIProcessGroup example.com From 712e90413337ef885b17ccb799921b377dfe2fb8 Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Fri, 30 Aug 2019 12:37:04 +0100 Subject: [PATCH 028/101] Describe usage of `manage.py document_correspondents` Relates to #347, without which I'd never have known it existed. --- docs/utilities.rst | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/docs/utilities.rst b/docs/utilities.rst index e95ef4725..e036392c1 100644 --- a/docs/utilities.rst +++ b/docs/utilities.rst @@ -193,17 +193,18 @@ instructions above to do the import. .. _utilities-retagger: -The Re-tagger +Re-running your tagging and correspondent matchers ------------- -Say you've imported a few hundred documents and now want to introduce a tag -and apply its matching to all of the currently-imported docs. This problem is -common enough that there's a tool for it. +Say you've imported a few hundred documents and now want to introduce +a tag or set up a new correspondent, and apply its matching to all of +the currently-imported docs. This problem is common enough that +there are tools for it. .. _utilities-retagger-howto: -How to Use It +How to Do It ............. This too is done via the ``manage.py`` script: @@ -212,10 +213,16 @@ This too is done via the ``manage.py`` script: $ /path/to/paperless/src/manage.py document_retagger -That's it. It'll loop over all of the documents in your database and attempt -to match all of your tags to them. If one matches, it'll be applied. And -don't worry, you can run this as often as you like, it won't double-tag -a document. +Run this after changing or adding tagging rules. It'll loop over all +of the documents in your database and attempt to match all of your +tags to them. If one matches, it'll be applied. And don't worry, you +can run this as often as you like, it won't double-tag a document. + +.. code:: bash + + $ /path/to/paperless/src/manage.py document_correspondents + +This is the similar command to run after adding or changing a correspondent. .. _utilities-encyption: From d0b513c18fbb37918bc77c7a57e8ba039820238e Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Fri, 30 Aug 2019 12:52:03 +0100 Subject: [PATCH 029/101] fix title underline length --- docs/utilities.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/utilities.rst b/docs/utilities.rst index e036392c1..069251b4a 100644 --- a/docs/utilities.rst +++ b/docs/utilities.rst @@ -194,7 +194,7 @@ instructions above to do the import. .. _utilities-retagger: Re-running your tagging and correspondent matchers -------------- +-------------------------------------------------- Say you've imported a few hundred documents and now want to introduce a tag or set up a new correspondent, and apply its matching to all of @@ -205,7 +205,7 @@ there are tools for it. .. _utilities-retagger-howto: How to Do It -............. +............ This too is done via the ``manage.py`` script: From 6ca7322aeed2f28e58ba4e0f5126f7159d9f70ac Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger Date: Fri, 30 Aug 2019 22:38:38 +0200 Subject: [PATCH 030/101] Move static file collection from docker entrypoint to Dockerfile to reduce superflous work --- Dockerfile | 2 ++ scripts/docker-entrypoint.sh | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index cfcfbd25c..0c47a9efa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,3 +65,5 @@ COPY src/ /usr/src/paperless/src/ COPY data/ /usr/src/paperless/data/ COPY media/ /usr/src/paperless/media/ +# Collect static files +RUN sudo -HEu paperless /usr/src/paperless/src/manage.py collectstatic --clear --no-input \ No newline at end of file diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index 303d1b8de..5cfcd4023 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -55,15 +55,10 @@ migrations() { fi } -collectstatic() { - sudo -HEu paperless "/usr/src/paperless/src/manage.py" "collectstatic" "--clear" "--no-input" -} - initialize() { map_uidgid set_permissions migrations - collectstatic } install_languages() { From f0320fb72d7059736ba1fc84c6781861c8415e49 Mon Sep 17 00:00:00 2001 From: Michael Gmelin Date: Sat, 18 May 2019 19:25:50 +0200 Subject: [PATCH 031/101] Allow configuring transformations to be applied to the filename before parsing. The motivation was that files produced by a Brother scanner wouldn't match paperless' expectations. At most one transformation is applied (first matching). It won't affect the filename on disk. This is generic enough so that it is useful for various purposes. In my case it allows me to use the different hardware buttons on the scanner to use different profiles, feeding one instance of paperless with documents of multiple entities and tagging them accordingly. Example: PAPERLESS_FILENAME_PARSE_TRANSFORMS=[{"pattern":"^([a-z]+)_(\\d{8})_(\\d{6})_([0-9]+)\\.", "repl":"\\2\\3Z - \\4 - \\1."},{"pattern":"^([a-z]+)_([0-9]+)\\.", "repl":" - \\2 - \\1."}] --- docs/guesswork.rst | 28 ++++++++++++++++++++++++++++ paperless.conf.example | 17 +++++++++++++++++ src/documents/models.py | 8 +++++++- src/paperless/settings.py | 11 +++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/docs/guesswork.rst b/docs/guesswork.rst index 0e728d7af..c12ecd0c4 100644 --- a/docs/guesswork.rst +++ b/docs/guesswork.rst @@ -54,6 +54,34 @@ filename as described above. .. _dateparser: https://github.com/scrapinghub/dateparser/blob/v0.7.0/docs/usage.rst#settings +Transforming filenames for parsing +---------------------------------- +Some devices can't produce filenames that can be parsed by the default +parser. By configuring the option ``PAPERLESS_FILENAME_PARSE_TRANSFORMS`` in +``paperless.conf`` one can add transformations that are applied to the filename +before it's parsed. + +The option contains a list of dictionaries of regular expressions (key: +``pattern``) and replacements (key: ``repl``) in JSON format, which are +applied in order by passing them to ``re.subn``. Transformation stops +after the first match, so at most one transformation is applied. The general +syntax is + +.. code:: python + + [{"pattern":"pattern1", "repl":"repl1"}, {"pattern":"pattern2", "repl":"repl2"}, ..., {"pattern":"patternN", "repl":"replN"}] + +The example below is for a Brother ADS-2400N, a scanner that allows +different names to different hardware buttons (useful for handling +multiple entities in one instance), but insists on adding ``_`` +to the filename. + +.. code:: python + + # Brother profile configuration, support "Name_Date_Count" (the default + # setting) and "Name_Count" (use "Name" as tag and "Count" as title). + PAPERLESS_FILENAME_PARSE_TRANSFORMS=[{"pattern":"^([a-z]+)_(\\d{8})_(\\d{6})_([0-9]+)\\.", "repl":"\\2\\3Z - \\4 - \\1."}, {"pattern":"^([a-z]+)_([0-9]+)\\.", "repl":" - \\2 - \\1."}] + .. _guesswork-content: Reading the Document Contents diff --git a/paperless.conf.example b/paperless.conf.example index 05a6c9cca..b04e93f94 100644 --- a/paperless.conf.example +++ b/paperless.conf.example @@ -135,6 +135,23 @@ PAPERLESS_EMAIL_SECRET="" # as normal. #PAPERLESS_FILENAME_DATE_ORDER="YMD" +# Sometimes devices won't create filenames which can be parsed properly +# by the filename parser (see +# https://paperless.readthedocs.io/en/latest/guesswork.html). +# +# This setting allows to specify a list of transformations +# in regular expression syntax, which are passed in order to re.sub. +# Transformation stops after the first match, so at most one transformation +# is applied. +# +# Syntax is a JSON array of dictionaries containing "pattern" and "repl" +# as keys. +# +# The example below transforms filenames created by a Brother ADS-2400N +# document scanner in its standard configuration `Name_Date_Count', so that +# count is used as title, name as tag and date can be parsed by paperless. +#PAPERLESS_FILENAME_PARSE_TRANSFORMS=[{"pattern":"^([a-z]+)_(\\d{8})_(\\d{6})_([0-9]+)\\.", "repl":"\\2\\3Z - \\4 - \\1."}] + # # The following values use sensible defaults for modern systems, but if you're # running Paperless on a low-resource device (like a Raspberry Pi), modifying diff --git a/src/documents/models.py b/src/documents/models.py index 37c1cfdbf..9647fbacd 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -483,8 +483,14 @@ def from_path(cls, path): ".<suffix>" """ + filename = os.path.basename(path) + for (pattern, repl) in settings.FILENAME_PARSE_TRANSFORMS: + (filename, count) = pattern.subn(repl, filename) + if count: + break + for regex in cls.REGEXES.values(): - m = regex.match(os.path.basename(path)) + m = regex.match(filename) if m: properties = m.groupdict() cls._mangle_property(properties, "created") diff --git a/src/paperless/settings.py b/src/paperless/settings.py index 917d1e64f..ad110d7bf 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -10,7 +10,9 @@ https://docs.djangoproject.com/en/1.10/ref/settings/ """ +import json import os +import re from dotenv import load_dotenv @@ -317,6 +319,15 @@ def __get_boolean(key, default="NO"): DATE_ORDER = os.getenv("PAPERLESS_DATE_ORDER", "DMY") FILENAME_DATE_ORDER = os.getenv("PAPERLESS_FILENAME_DATE_ORDER") +# Transformations applied before filename parsing +FILENAME_PARSE_TRANSFORMS = [] +_filename_parse_transforms = os.getenv("PAPERLESS_FILENAME_PARSE_TRANSFORMS") +if _filename_parse_transforms: + FILENAME_PARSE_TRANSFORMS = [( + re.compile(t["pattern"]), t["repl"]) + for t in json.loads(_filename_parse_transforms) + ] + # Specify for how many years a correspondent is considered recent. Recent # correspondents will be shown in a separate "Recent correspondents" filter as # well. Set to 0 to disable this filter. From 3050ff159466e873e3542e898e76848d6aaae3e6 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger <florian.gabsteiger@methodpark.com> Date: Wed, 4 Sep 2019 23:00:34 +0200 Subject: [PATCH 032/101] Upgrade docker base image to alpine v3.10 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cfcfbd25c..69ad48aca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.8 +FROM alpine:3.10 LABEL maintainer="The Paperless Project https://github.com/the-paperless-project/paperless" \ contributors="Guy Addadi <addadi@gmail.com>, Pit Kleyersburg <pitkley@googlemail.com>, \ From 3b88d6722a32c983062a1fd4c4fed8642e39f809 Mon Sep 17 00:00:00 2001 From: Michael Gmelin <freebsd@grem.de> Date: Sun, 8 Sep 2019 17:00:02 +0200 Subject: [PATCH 033/101] Address review comments by @danielquinn --- src/documents/models.py | 4 ++++ src/paperless/settings.py | 8 ++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 9647fbacd..c6fc8191e 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -484,11 +484,15 @@ def from_path(cls, path): """ filename = os.path.basename(path) + + # Mutate filename in-place before parsing its components + # by applying at most one of the configured transformations. for (pattern, repl) in settings.FILENAME_PARSE_TRANSFORMS: (filename, count) = pattern.subn(repl, filename) if count: break + # Parse filename components. for regex in cls.REGEXES.values(): m = regex.match(filename) if m: diff --git a/src/paperless/settings.py b/src/paperless/settings.py index ad110d7bf..b6bc67ef0 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -321,12 +321,8 @@ def __get_boolean(key, default="NO"): # Transformations applied before filename parsing FILENAME_PARSE_TRANSFORMS = [] -_filename_parse_transforms = os.getenv("PAPERLESS_FILENAME_PARSE_TRANSFORMS") -if _filename_parse_transforms: - FILENAME_PARSE_TRANSFORMS = [( - re.compile(t["pattern"]), t["repl"]) - for t in json.loads(_filename_parse_transforms) - ] +for t in json.loads(os.getenv("PAPERLESS_FILENAME_PARSE_TRANSFORMS", "[]")): + FILENAME_PARSE_TRANSFORMS.append((re.compile(t["pattern"]), t["repl"])) # Specify for how many years a correspondent is considered recent. Recent # correspondents will be shown in a separate "Recent correspondents" filter as From 4f85d9ed9f450e10afb390ed0ff989ca40cede6d Mon Sep 17 00:00:00 2001 From: Michael Gmelin <freebsd@grem.de> Date: Sun, 8 Sep 2019 20:24:58 +0200 Subject: [PATCH 034/101] Add unit test for PAPERLESS_FILENAME_PARSE_TRANSFORMS feature. --- src/documents/tests/test_consumer.py | 78 ++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/documents/tests/test_consumer.py b/src/documents/tests/test_consumer.py index 3f5c69774..512447741 100644 --- a/src/documents/tests/test_consumer.py +++ b/src/documents/tests/test_consumer.py @@ -1,3 +1,5 @@ +import re + from django.test import TestCase from unittest import mock from tempfile import TemporaryDirectory @@ -372,3 +374,79 @@ def test_invalid_date_format(self): info = FileInfo.from_path("/path/to/06112017Z - title.pdf") self.assertEqual(info.title, "title") self.assertIsNone(info.created) + + def test_filename_parse_transforms(self): + + path = "/some/path/to/tag1,tag2_20190908_180610_0001.pdf" + all_patt = re.compile("^.*$") + none_patt = re.compile("$a") + exact_patt = re.compile("^([a-z0-9,]+)_(\\d{8})_(\\d{6})_([0-9]+)\\.") + repl1 = " - \\4 - \\1." # (empty) corrspondent, title and tags + repl2 = "\\2Z - " + repl1 # creation date + repl1 + + # No transformations configured (= default) + info = FileInfo.from_path(path) + self.assertEqual(info.title, "tag1,tag2_20190908_180610_0001") + self.assertEqual(info.extension, "pdf") + self.assertEqual(info.tags, ()) + self.assertIsNone(info.created) + + # Pattern doesn't match (filename unaltered) + with self.settings( + FILENAME_PARSE_TRANSFORMS=[(none_patt, "none.gif")]): + info = FileInfo.from_path(path) + self.assertEqual(info.title, "tag1,tag2_20190908_180610_0001") + self.assertEqual(info.extension, "pdf") + + # Simple transformation (match all) + with self.settings( + FILENAME_PARSE_TRANSFORMS=[(all_patt, "all.gif")]): + info = FileInfo.from_path(path) + self.assertEqual(info.title, "all") + self.assertEqual(info.extension, "gif") + + # Multiple transformations configured (first pattern matches) + with self.settings( + FILENAME_PARSE_TRANSFORMS=[ + (all_patt, "all.gif"), + (all_patt, "anotherall.gif")]): + info = FileInfo.from_path(path) + self.assertEqual(info.title, "all") + self.assertEqual(info.extension, "gif") + + # Multiple transformations configured (second pattern matches) + with self.settings( + FILENAME_PARSE_TRANSFORMS=[ + (none_patt, "none.gif"), + (all_patt, "anotherall.gif")]): + info = FileInfo.from_path(path) + self.assertEqual(info.title, "anotherall") + self.assertEqual(info.extension, "gif") + + # Complex transformation without date in replacement string + with self.settings( + FILENAME_PARSE_TRANSFORMS=[(exact_patt, repl1)]): + info = FileInfo.from_path(path) + self.assertEqual(info.title, "0001") + self.assertEqual(info.extension, "pdf") + self.assertEqual(len(info.tags), 2) + self.assertEqual(info.tags[0].slug, "tag1") + self.assertEqual(info.tags[1].slug, "tag2") + self.assertIsNone(info.created) + + # Complex transformation with date in replacement string + with self.settings( + FILENAME_PARSE_TRANSFORMS=[ + (none_patt, "none.gif"), + (exact_patt, repl2), # <-- matches + (exact_patt, repl1), + (all_patt, "all.gif")]): + info = FileInfo.from_path(path) + self.assertEqual(info.title, "0001") + self.assertEqual(info.extension, "pdf") + self.assertEqual(len(info.tags), 2) + self.assertEqual(info.tags[0].slug, "tag1") + self.assertEqual(info.tags[1].slug, "tag2") + self.assertEqual(info.created.year, 2019) + self.assertEqual(info.created.month, 9) + self.assertEqual(info.created.day, 8) From dcc959d4f7b9700edc4c5faafe7f943dba97757e Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger <florian.g@me.com> Date: Fri, 9 Aug 2019 00:44:41 +0200 Subject: [PATCH 035/101] Add gunicorn option to docker-entrypoint script --- scripts/docker-entrypoint.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index 5cfcd4023..bc4824a86 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -99,7 +99,12 @@ if [[ "$1" != "/"* ]]; then install_languages "$PAPERLESS_OCR_LANGUAGES" fi - exec sudo -HEu paperless "/usr/src/paperless/src/manage.py" "$@" + if [[ "$1" = "gunicorn" ]]; then + cd /usr/src/paperless/src/ && \ + exec sudo -HEu paperless /usr/bin/gunicorn -c gunicorn.conf paperless.wsgi + else + exec sudo -HEu paperless "/usr/src/paperless/src/manage.py" "$@" + fi fi exec "$@" From bdeaf33462697639b872386a5d4b67d65f3de5e2 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger <florian.gabsteiger@methodpark.com> Date: Fri, 9 Aug 2019 13:39:57 -0900 Subject: [PATCH 036/101] Copy gunicorn.conf to docker container and use it in entrypoint --- Dockerfile | 3 ++- docker-compose.yml.example | 2 +- scripts/docker-entrypoint.sh | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 51c919b20..30eb3a5bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,9 +4,10 @@ LABEL maintainer="The Paperless Project https://github.com/the-paperless-project contributors="Guy Addadi <addadi@gmail.com>, Pit Kleyersburg <pitkley@googlemail.com>, \ Sven Fischer <git-dev@linux4tw.de>" -# Copy Pipfiles file and init script +# Copy Pipfiles file, init script and gunicorn.conf COPY Pipfile* /usr/src/paperless/ COPY scripts/docker-entrypoint.sh /sbin/docker-entrypoint.sh +COPY scripts/gunicorn.conf /usr/src/paperless/ # Set export and consumption directories ENV PAPERLESS_EXPORT_DIR=/export \ diff --git a/docker-compose.yml.example b/docker-compose.yml.example index 312467b91..5a6a5ed0e 100644 --- a/docker-compose.yml.example +++ b/docker-compose.yml.example @@ -27,7 +27,7 @@ services: # value with nothing. environment: - PAPERLESS_OCR_LANGUAGES= - command: ["runserver", "--insecure", "--noreload", "0.0.0.0:8000"] + command: ["gunicorn"] consumer: build: ./ diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index bc4824a86..8e6b819e0 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -101,7 +101,7 @@ if [[ "$1" != "/"* ]]; then if [[ "$1" = "gunicorn" ]]; then cd /usr/src/paperless/src/ && \ - exec sudo -HEu paperless /usr/bin/gunicorn -c gunicorn.conf paperless.wsgi + exec sudo -HEu paperless /usr/bin/gunicorn -c /usr/src/paperless/gunicorn.conf paperless.wsgi else exec sudo -HEu paperless "/usr/src/paperless/src/manage.py" "$@" fi From d390005c5c7d357732855bdbfa3a0859e4689d91 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger <florian.gabsteiger@methodpark.com> Date: Sat, 21 Sep 2019 15:45:10 +0200 Subject: [PATCH 037/101] Enable user-controlled gunicorn options in docker-compose file --- scripts/docker-entrypoint.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index 8e6b819e0..14f431b64 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -100,8 +100,9 @@ if [[ "$1" != "/"* ]]; then fi if [[ "$1" = "gunicorn" ]]; then + shift cd /usr/src/paperless/src/ && \ - exec sudo -HEu paperless /usr/bin/gunicorn -c /usr/src/paperless/gunicorn.conf paperless.wsgi + exec sudo -HEu paperless /usr/bin/gunicorn -c /usr/src/paperless/gunicorn.conf "$@" paperless.wsgi else exec sudo -HEu paperless "/usr/src/paperless/src/manage.py" "$@" fi From da586fc90af41617453af384c13b965d515c7642 Mon Sep 17 00:00:00 2001 From: Florian Gabsteiger <florian.gabsteiger@methodpark.com> Date: Sun, 22 Sep 2019 00:33:14 +0200 Subject: [PATCH 038/101] Add bind-ip 0.0.0.0 to docker-compose command --- docker-compose.yml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml.example b/docker-compose.yml.example index 5a6a5ed0e..f8c920f95 100644 --- a/docker-compose.yml.example +++ b/docker-compose.yml.example @@ -27,7 +27,7 @@ services: # value with nothing. environment: - PAPERLESS_OCR_LANGUAGES= - command: ["gunicorn"] + command: ["gunicorn", "-b", "0.0.0.0:8000"] consumer: build: ./ From 12f0df0f52b0859253856d04ef950fa567360f97 Mon Sep 17 00:00:00 2001 From: Matthias Brandt <matthias.brandt@inoio.de> Date: Sat, 5 Oct 2019 18:08:06 +0200 Subject: [PATCH 039/101] fix: Documentation rendering leads to wrong commands #569 --- docs/setup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/setup.rst b/docs/setup.rst index 369205ba1..ed9a0b49f 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -159,7 +159,7 @@ Docker Method If you are using NFS mounts for the consume directory you also need to change the command to turn off inotify as it doesn't work with NFS - `command: ["document_consumer", "--no-inotify"]` + ``command: ["document_consumer", "--no-inotify"]`` 5. Modify ``docker-compose.env`` and adapt the following environment variables: From 9b2b435c5b6200595e2ba9089f0143c27b5c38ea Mon Sep 17 00:00:00 2001 From: Fabian Winter <5821180+fdw@users.noreply.github.com> Date: Sun, 3 Nov 2019 18:24:03 +0100 Subject: [PATCH 040/101] Support SSL for web interface Thanks to @MasterofJOKers, here is basic support for SSL: You need to create your key and certificate and copy them to the `data` directory, named `ssl.cert` and `ssl.key`. Then, set `PAPERLESS_USE_SSL` in `docker-compose.env` to `true`. Solves #576. --- docker-compose.env.example | 1 + docs/setup.rst | 8 +++++++- scripts/docker-entrypoint.sh | 8 +++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docker-compose.env.example b/docker-compose.env.example index 51332437d..d939a327a 100644 --- a/docker-compose.env.example +++ b/docker-compose.env.example @@ -16,6 +16,7 @@ # different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the # default language used when guessing the language from the OCR output. # PAPERLESS_OCR_LANGUAGES=deu ita +# PAPERLESS_USE_SSL=false # You can change the default user and group id to a custom one # USERMAP_UID=1000 diff --git a/docs/setup.rst b/docs/setup.rst index ed9a0b49f..288ca7405 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -193,6 +193,11 @@ Docker Method container and thus the one of the consumption directory. Furthermore, you can change the id of the default user as well using ``USERMAP_UID``. + ``USE_SSL`` + If you want Paperless to use SSL for the user interface, set this variable + to ``true``. You also need to copy your certificate and key to the ``data`` + directory, named ``ssl.cert`` and ``ssl.key``. + 6. Run ``docker-compose up -d``. This will create and start the necessary containers. 7. To be able to login, you will need a super user. To create it, execute the @@ -206,7 +211,8 @@ Docker Method e-mail address and finally a password. 8. The default ``docker-compose.yml`` exports the webserver on your local port 8000. If you haven't adapted this, you should now be able to visit your - `Paperless webserver`_ at ``http://127.0.0.1:8000``. You can login with the + `Paperless webserver`_ at ``http://127.0.0.1:8000`` (or + ``https://127.0.0.1:8000`` if you enabled SSL). You can login with the user and password you just created. 9. Add files to consumption directory the way you prefer to. Following are two possible options: diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index 14f431b64..df629554a 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -101,8 +101,14 @@ if [[ "$1" != "/"* ]]; then if [[ "$1" = "gunicorn" ]]; then shift + EXTRA_PARAMS="" + SSL_KEY_PATH="/usr/src/paperless/data/ssl.key" + SSL_CERT_PATH="/usr/src/paperless/data/ssl.cert" + if [ "${PAPERLESS_USE_SSL}" = "true" ] && [ -f "${SSL_KEY_PATH}" ] && [ -f "${SSL_CERT_PATH}" ]; then + EXTRA_PARAMS="--certfile=${SSL_CERT_PATH} --keyfile=${SSL_KEY_PATH}" + fi cd /usr/src/paperless/src/ && \ - exec sudo -HEu paperless /usr/bin/gunicorn -c /usr/src/paperless/gunicorn.conf "$@" paperless.wsgi + exec sudo -HEu paperless /usr/bin/gunicorn -c /usr/src/paperless/gunicorn.conf ${EXTRA_PARAMS} "$@" paperless.wsgi else exec sudo -HEu paperless "/usr/src/paperless/src/manage.py" "$@" fi From 9c1fcbcc9890dbf453bd469984cb0eb5a0f7eccd Mon Sep 17 00:00:00 2001 From: Fabian Winter <5821180+fdw@users.noreply.github.com> Date: Sun, 3 Nov 2019 20:14:17 +0100 Subject: [PATCH 041/101] Address comments --- docker-compose.env.example | 3 +++ docs/setup.rst | 4 +++- scripts/docker-entrypoint.sh | 8 ++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docker-compose.env.example b/docker-compose.env.example index d939a327a..50c1690be 100644 --- a/docker-compose.env.example +++ b/docker-compose.env.example @@ -16,6 +16,9 @@ # different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the # default language used when guessing the language from the OCR output. # PAPERLESS_OCR_LANGUAGES=deu ita + +# Set Paperless to use SSL for the web interface. +# Enabling this will require ssl.key and ssl.cert files in paperless' data directory. # PAPERLESS_USE_SSL=false # You can change the default user and group id to a custom one diff --git a/docs/setup.rst b/docs/setup.rst index 288ca7405..9a371f889 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -193,10 +193,12 @@ Docker Method container and thus the one of the consumption directory. Furthermore, you can change the id of the default user as well using ``USERMAP_UID``. - ``USE_SSL`` + ``PAPERLESS_USE_SSL`` If you want Paperless to use SSL for the user interface, set this variable to ``true``. You also need to copy your certificate and key to the ``data`` directory, named ``ssl.cert`` and ``ssl.key``. + This is not an ideal solution and, if possible, a reverse proxy with nginx + is preferred. 6. Run ``docker-compose up -d``. This will create and start the necessary containers. diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index df629554a..d2451720e 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -104,8 +104,12 @@ if [[ "$1" != "/"* ]]; then EXTRA_PARAMS="" SSL_KEY_PATH="/usr/src/paperless/data/ssl.key" SSL_CERT_PATH="/usr/src/paperless/data/ssl.cert" - if [ "${PAPERLESS_USE_SSL}" = "true" ] && [ -f "${SSL_KEY_PATH}" ] && [ -f "${SSL_CERT_PATH}" ]; then - EXTRA_PARAMS="--certfile=${SSL_CERT_PATH} --keyfile=${SSL_KEY_PATH}" + if [ "${PAPERLESS_USE_SSL}" = "true" ]; then + if [ -f "${SSL_KEY_PATH}" ] && [ -f "${SSL_CERT_PATH}" ]; then + EXTRA_PARAMS="--certfile=${SSL_CERT_PATH} --keyfile=${SSL_KEY_PATH}" + else + echo "Error: Could not find certfile in ${SSL_CERT_PATH} or keyfile in ${SSL_KEY_PATH}, but \$PAPERLESS_USE_SSL is true. Starting without SSL enabled." + fi fi cd /usr/src/paperless/src/ && \ exec sudo -HEu paperless /usr/bin/gunicorn -c /usr/src/paperless/gunicorn.conf ${EXTRA_PARAMS} "$@" paperless.wsgi From 2cb172b4aa8d84724976c13319ad14810d49a09f Mon Sep 17 00:00:00 2001 From: nxnjz <43261757+nxnjz@users.noreply.github.com> Date: Tue, 19 Nov 2019 22:16:53 +0200 Subject: [PATCH 042/101] added dependency on network.target --- scripts/paperless-webserver.service | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/paperless-webserver.service b/scripts/paperless-webserver.service index 771b8301f..8fd160c4b 100644 --- a/scripts/paperless-webserver.service +++ b/scripts/paperless-webserver.service @@ -1,5 +1,7 @@ [Unit] Description=Paperless webserver +After=network.target +Requires=network.target [Service] User=paperless From 6813805712d41bb4d5dca89aaaef43d47f3acdf9 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Fri, 27 Dec 2019 14:13:18 +0000 Subject: [PATCH 043/101] Allows to configure directory and filename formats for documents stored in paperless Default configuration is as before (incrementing numbers), but additional fields can be added at will --- paperless.conf.example | 11 ++ src/documents/consumer.py | 3 + .../0023_document_current_filename.py | 37 +++++ src/documents/models.py | 141 +++++++++++++++++- src/paperless/settings.py | 4 + 5 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 src/documents/migrations/0023_document_current_filename.py diff --git a/paperless.conf.example b/paperless.conf.example index b04e93f94..67e1b1c89 100644 --- a/paperless.conf.example +++ b/paperless.conf.example @@ -54,6 +54,17 @@ PAPERLESS_CONSUME_MAIL_PASS="" # ignored. PAPERLESS_EMAIL_SECRET="" +# Specify a filename format for an (optional) subdirectory and the document itself +# Use the following placefolders: +# * {correspondent} +# * {title} +# * {created} +# * {added} +# * {tags[FILTER]} +# Uniqueness of filenames is ensured, as an incrementing counter is attached +# to each filename. +#PAPERLESS_DIRECTORY_FORMAT="" +#PAPERLESS_FILENAME_FORMAT="" ############################################################################### #### Security #### diff --git a/src/documents/consumer.py b/src/documents/consumer.py index 3cb484b2a..d846691f9 100644 --- a/src/documents/consumer.py +++ b/src/documents/consumer.py @@ -234,6 +234,9 @@ def _store(self, text, doc, thumbnail, date): self._write(document, doc, document.source_path) self._write(document, thumbnail, document.thumbnail_path) + document.set_filename(document.source_filename) + document.save() + self.log("info", "Completed") return document diff --git a/src/documents/migrations/0023_document_current_filename.py b/src/documents/migrations/0023_document_current_filename.py new file mode 100644 index 000000000..be78ea863 --- /dev/null +++ b/src/documents/migrations/0023_document_current_filename.py @@ -0,0 +1,37 @@ +# Generated by Django 2.0.10 on 2019-04-26 18:57 + +from django.db import migrations, models + + +def set_filename(apps, schema_editor): + Document = apps.get_model("documents", "Document") + for doc in Document.objects.all(): + file_name = "{:07}.{}".format(doc.pk, doc.file_type) + if doc.storage_type == "gpg": + file_name += ".gpg" + + # Set filename + doc.filename = file_name + + # Save document + doc.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('documents', '0022_auto_20181007_1420'), + ] + + operations = [ + migrations.AddField( + model_name='document', + name='filename', + field=models.FilePathField(default=None, + null=True, + editable=False, + help_text='Current filename in storage', + max_length=256), + ), + migrations.RunPython(set_filename) + ] diff --git a/src/documents/models.py b/src/documents/models.py index c6fc8191e..25e5621b3 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -7,12 +7,14 @@ from collections import OrderedDict import dateutil.parser +from django.dispatch import receiver from django.conf import settings from django.db import models from django.template.defaultfilters import slugify from django.utils import timezone from django.utils.text import slugify from fuzzywuzzy import fuzz +from collections import defaultdict from .managers import LogManager @@ -254,6 +256,14 @@ class Document(models.Model): added = models.DateTimeField( default=timezone.now, editable=False, db_index=True) + filename = models.CharField( + max_length=256, + editable=False, + default=None, + null=True, + help_text="Current filename in storage" + ) + class Meta: ordering = ("correspondent", "title") @@ -267,17 +277,90 @@ def __str__(self): return str(created) @property - def source_path(self): - - file_name = "{:07}.{}".format(self.pk, self.file_type) + def source_filename(self): + if self.filename is None: + self.filename = self.source_filename_new() + + return self.filename + + def many_to_list(self, field): + mylist = [] + for t in field.all(): + mylist.append(t.name) + return mylist + + def many_to_dictionary(self, field): + mydictionary = dict() + for t in field.all(): + delimeter = t.name.find('_') + + if delimeter is -1: + continue + + key = t.name[:delimeter] + value = t.name[delimeter+1:] + + mydictionary[key] = value + + return mydictionary + + def source_filename_new(self): + # Create directory name based on configured format + if settings.PAPERLESS_DIRECTORY_FORMAT is not None: + directory = settings.PAPERLESS_DIRECTORY_FORMAT.format( + correspondent=self.correspondent, + title=self.title, + created=self.created, + added=self.added, + tags=defaultdict(str, + self.many_to_dictionary(self.tags))) + else: + directory = "" + + # Create filename based on configured format + if settings.PAPERLESS_FILENAME_FORMAT is not None: + filename = settings.PAPERLESS_FILENAME_FORMAT.format( + correspondent=self.correspondent, + title=self.title, + created=self.created, + added=self.added, + tags=defaultdict(str, + self.many_to_dictionary(self.tags))) + else: + filename = "" + + path = os.path.join(slugify(directory), slugify(filename)) + + # Always append the primary key to guarantee uniqueness of filename + if len(path) > 0: + filename = "%s-%07i.%s" % (path, self.pk, self.file_type) + else: + filename = "%07i.%s" % (self.pk, self.file_type) + + # Append .gpg for encrypted files if self.storage_type == self.STORAGE_TYPE_GPG: - file_name += ".gpg" + filename += ".gpg" + # Create directory for target + create_dir = self.filename_to_path(slugify(directory)) + try: + os.makedirs(create_dir) + except os.error: + # Directory existed already, ignore + pass + + return filename + + @property + def source_path(self): + return self.filename_to_path(self.source_filename) + + def filename_to_path(self, filename): return os.path.join( settings.MEDIA_ROOT, "documents", "originals", - file_name + filename ) @property @@ -314,6 +397,54 @@ def thumbnail_file(self): def thumbnail_url(self): return reverse("fetch", kwargs={"kind": "thumb", "pk": self.pk}) + def set_filename(self, filename): + if os.path.isfile(self.filename_to_path(filename)): + self.filename = filename + + +@receiver(models.signals.m2m_changed, sender=Document.tags.through) +@receiver(models.signals.post_save, sender=Document) +def update_filename(sender, instance, **kwargs): + if instance.filename is None: + return + + # Build the new filename + new_filename = instance.source_filename_new() + + # If the filename is the same, then nothing needs to be done + if instance.filename is None or \ + instance.filename == new_filename: + return + + # Check if filename needs changing + if new_filename != instance.filename: + # Determine the full "target" path + path_new = instance.filename_to_path(new_filename) + dir_new = instance.filename_to_path(os.path.dirname(new_filename)) + + # Determine the full "current" path + path_current = instance.filename_to_path(instance.filename) + + # Move file + os.rename(path_current, path_new) + + # Delete empty directory + old_dir = os.path.dirname(instance.filename) + old_path = instance.filename_to_path(old_dir) + if len(os.listdir(old_path)) == 0: + try: + os.rmdir(old_path) + except os.error: + # Directory not empty + pass + + instance.filename = new_filename + + # Save instance + # This will not cause a cascade of post_save signals, as next time + # nothing needs to be renamed + instance.save() + class Log(models.Model): diff --git a/src/paperless/settings.py b/src/paperless/settings.py index ddc903857..4a7317e02 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -334,3 +334,7 @@ def __get_boolean(key, default="NO"): # well. Set to 0 to disable this filter. PAPERLESS_RECENT_CORRESPONDENT_YEARS = int(os.getenv( "PAPERLESS_RECENT_CORRESPONDENT_YEARS", 0)) + +# Specify the filename format for out files +PAPERLESS_DIRECTORY_FORMAT = os.getenv("PAPERLESS_DIRECTORY_FORMAT") +PAPERLESS_FILENAME_FORMAT = os.getenv("PAPERLESS_FILENAME_FORMAT") From a79a0ca302edc5f1248e2ffe1a094c564eb61da2 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Fri, 27 Dec 2019 14:13:25 +0000 Subject: [PATCH 044/101] Added tool to rename all documents according to the lastest filename format --- .../management/commands/document_renamer.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/documents/management/commands/document_renamer.py diff --git a/src/documents/management/commands/document_renamer.py b/src/documents/management/commands/document_renamer.py new file mode 100644 index 000000000..d7d77a111 --- /dev/null +++ b/src/documents/management/commands/document_renamer.py @@ -0,0 +1,24 @@ +from django.core.management.base import BaseCommand + +from documents.models import Document, Tag + +from ...mixins import Renderable + + +class Command(Renderable, BaseCommand): + + help = """ + This will rename all documents to match the latest filename format. + """.replace(" ", "") + + def __init__(self, *args, **kwargs): + self.verbosity = 0 + BaseCommand.__init__(self, *args, **kwargs) + + def handle(self, *args, **options): + + self.verbosity = options["verbosity"] + + for document in Document.objects.all(): + # Saving the document again will generate a new filename and rename + document.save() From 1ce6c6e2c50d949ab8b05d915ae23d8b2b42032c Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Fri, 27 Dec 2019 14:13:28 +0000 Subject: [PATCH 045/101] Add unit tests for filename feature --- src/documents/models.py | 88 ++++++++----- src/documents/tests/test_file_handling.py | 154 ++++++++++++++++++++++ 2 files changed, 209 insertions(+), 33 deletions(-) create mode 100644 src/documents/tests/test_file_handling.py diff --git a/src/documents/models.py b/src/documents/models.py index 25e5621b3..741b7079e 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -256,7 +256,7 @@ class Document(models.Model): added = models.DateTimeField( default=timezone.now, editable=False, db_index=True) - filename = models.CharField( + filename = models.FilePathField( max_length=256, editable=False, default=None, @@ -402,48 +402,70 @@ def set_filename(self, filename): self.filename = filename +def delete_empty_directory(directory): + if len(os.listdir(directory)) == 0: + try: + os.rmdir(directory) + except os.error: + # Directory not empty + pass + @receiver(models.signals.m2m_changed, sender=Document.tags.through) @receiver(models.signals.post_save, sender=Document) def update_filename(sender, instance, **kwargs): - if instance.filename is None: - return + if instance.filename is None: + return - # Build the new filename - new_filename = instance.source_filename_new() + # Build the new filename + new_filename = instance.source_filename_new() - # If the filename is the same, then nothing needs to be done - if instance.filename is None or \ - instance.filename == new_filename: - return + # If the filename is the same, then nothing needs to be done + if instance.filename is None or \ + instance.filename == new_filename: + return - # Check if filename needs changing - if new_filename != instance.filename: - # Determine the full "target" path - path_new = instance.filename_to_path(new_filename) - dir_new = instance.filename_to_path(os.path.dirname(new_filename)) + # Check if filename needs changing + if new_filename != instance.filename: + # Determine the full "target" path + path_new = instance.filename_to_path(new_filename) + dir_new = instance.filename_to_path(os.path.dirname(new_filename)) - # Determine the full "current" path - path_current = instance.filename_to_path(instance.filename) + # Determine the full "current" path + path_current = instance.filename_to_path(instance.filename) - # Move file + # Move file + try: os.rename(path_current, path_new) + except PermissionError: + # Do not update filename in object + return + + # Delete empty directory + old_dir = os.path.dirname(instance.filename) + old_path = instance.filename_to_path(old_dir) + delete_empty_directory(old_path) + + instance.filename = new_filename + + # Save instance + # This will not cause a cascade of post_save signals, as next time + # nothing needs to be renamed + instance.save() + + +@receiver(models.signals.post_delete, sender=Document) +def delete_files(sender, instance, **kwargs): + if instance.filename is None: + return + + # Remove the document + old_file = instance.filename_to_path(instance.filename) + os.remove(old_file) - # Delete empty directory - old_dir = os.path.dirname(instance.filename) - old_path = instance.filename_to_path(old_dir) - if len(os.listdir(old_path)) == 0: - try: - os.rmdir(old_path) - except os.error: - # Directory not empty - pass - - instance.filename = new_filename - - # Save instance - # This will not cause a cascade of post_save signals, as next time - # nothing needs to be renamed - instance.save() + # And remove the directory (if applicable) + old_dir = os.path.dirname(instance.filename) + old_path = instance.filename_to_path(old_dir) + delete_empty_directory(old_path) class Log(models.Model): diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py new file mode 100644 index 000000000..edeb1ab5e --- /dev/null +++ b/src/documents/tests/test_file_handling.py @@ -0,0 +1,154 @@ +import datetime +import os +import shutil +from unittest import mock +from uuid import uuid4 +from pathlib import Path + +from dateutil import tz +from django.test import TestCase, override_settings + +from django.utils.text import slugify +from ..models import Document, Correspondent +from django.conf import settings + + +class TestDate(TestCase): + @override_settings(PAPERLESS_DIRECTORY_FORMAT="") + @override_settings(PAPERLESS_FILENAME_FORMAT="") + def test_source_filename(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + self.assertEqual(document.source_filename, "0000001.pdf") + + document.filename = "test.pdf" + self.assertEqual(document.source_filename, "test.pdf") + + @override_settings(PAPERLESS_DIRECTORY_FORMAT="") + @override_settings(PAPERLESS_FILENAME_FORMAT="") + def test_source_filename_new(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + self.assertEqual(document.source_filename_new(), "0000001.pdf") + + document.storage_type = Document.STORAGE_TYPE_GPG + self.assertEqual(document.source_filename_new(), "0000001.pdf.gpg") + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_DIRECTORY_FORMAT="{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}") + def test_file_renaming(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.source_filename_new(), + "none/none-0000001.pdf") + Path(document.source_path).touch() + + # Test source_path + self.assertEqual(document.source_path, settings.MEDIA_ROOT + + "/documents/originals/none/none-0000001.pdf") + + # Enable encryption and check again + document.storage_type = Document.STORAGE_TYPE_GPG + tmp = document.source_filename + self.assertEqual(document.source_filename_new(), + "none/none-0000001.pdf.gpg") + document.save() + + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none"), True) + + # Set a correspondent and save the document + document.correspondent = Correspondent.objects.get_or_create( + name="test")[0] + document.save() + + # Check proper handling of files + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/test"), True) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none"), False) + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + + "originals/test/test-0000001.pdf.gpg"), True) + self.assertEqual(document.source_filename_new(), + "test/test-0000001.pdf.gpg") + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_DIRECTORY_FORMAT="{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}") + def test_document_delete(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.source_filename_new(), + "none/none-0000001.pdf") + Path(document.source_path).touch() + + # Ensure file deletion after delete + document.delete() + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + + "/documents/originals/none/none-0000001.pdf"), False) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none"), False) + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_DIRECTORY_FORMAT="{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}") + def test_directory_not_empty(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.source_filename_new(), + "none/none-0000001.pdf") + Path(document.source_path).touch() + Path(document.source_path + "test").touch() + + # Set a correspondent and save the document + document.correspondent = Correspondent.objects.get_or_create( + name="test")[0] + document.save() + + # Check proper handling of files + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/test"), True) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none"), True) + + # Cleanup + os.remove(settings.MEDIA_ROOT + + "/documents/originals/none/none-0000001.pdftest") + os.rmdir(settings.MEDIA_ROOT + "/documents/originals/none") + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_DIRECTORY_FORMAT=None) + @override_settings(PAPERLESS_FILENAME_FORMAT=None) + def test_format_none(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + self.assertEqual(document.source_filename_new(), "0000001.pdf") From 79976d18ab3cd356f0e952879cf9b3e1ecf79a6b Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Fri, 27 Dec 2019 14:13:29 +0000 Subject: [PATCH 046/101] Check if document file exist before deletion --- src/documents/models.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/documents/models.py b/src/documents/models.py index 741b7079e..0a69434e0 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -410,6 +410,7 @@ def delete_empty_directory(directory): # Directory not empty pass + @receiver(models.signals.m2m_changed, sender=Document.tags.through) @receiver(models.signals.post_save, sender=Document) def update_filename(sender, instance, **kwargs): @@ -460,7 +461,13 @@ def delete_files(sender, instance, **kwargs): # Remove the document old_file = instance.filename_to_path(instance.filename) - os.remove(old_file) + + if os.path.isfile(old_file): + os.remove(old_file) + else: + logger = logging.getLogger(__name__) + logger.warning("Deleted document " + str(instance.id) + " but file " + + old_file + " was no longer present") # And remove the directory (if applicable) old_dir = os.path.dirname(instance.filename) From 22c7f309a76dcbfb60fc710f6f676700ede640d9 Mon Sep 17 00:00:00 2001 From: Johann Bauer <bauerj@bauerj.eu> Date: Mon, 6 May 2019 09:46:04 +0200 Subject: [PATCH 047/101] Warn if consume directory contains subdirectories . --- src/documents/consumer.py | 5 +++++ src/documents/management/commands/document_consumer.py | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/documents/consumer.py b/src/documents/consumer.py index 3cb484b2a..4e9f17116 100644 --- a/src/documents/consumer.py +++ b/src/documents/consumer.py @@ -94,6 +94,11 @@ def consume_new_files(self): ignored_files.append(file) else: files.append(file) + else: + self.logger.warning( + "Skipping %s as it is not a file", + entry.path + ) if not files: return diff --git a/src/documents/management/commands/document_consumer.py b/src/documents/management/commands/document_consumer.py index 6f731372f..8a6ccfcdd 100644 --- a/src/documents/management/commands/document_consumer.py +++ b/src/documents/management/commands/document_consumer.py @@ -26,6 +26,7 @@ class Command(BaseCommand): def __init__(self, *args, **kwargs): self.verbosity = 0 + self.logger = logging.getLogger(__name__) self.file_consumer = None self.mail_fetcher = None @@ -138,6 +139,11 @@ def loop_inotify(self, mail_delta): file = os.path.join(directory, event.name) if os.path.isfile(file): self.file_consumer.try_consume_file(file) + else: + self.logger.warning( + "Skipping %s as it is not a file", + file + ) else: break From ad42e7fabe4da633664f03b550a422cc574a25e0 Mon Sep 17 00:00:00 2001 From: ljm42 <larry_meaney@iname.com> Date: Sun, 5 Jan 2020 18:20:03 -0800 Subject: [PATCH 048/101] Allow non-unique GIDs Need to allow non-unique group ids, so paperless can map to an existing GID. The comment says the map_uidgid() function came from docker-gitlab, the same fix was applied there too: https://github.com/sameersbn/docker-gitlab/commit/c80bd876628d0c04f8ef2a3ffb46fe899bf63d23 --- scripts/docker-entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index d2451720e..2028413d1 100644 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -10,7 +10,7 @@ map_uidgid() { if [[ ${USERMAP_NEW_UID} != "${USERMAP_ORIG_UID}" || ${USERMAP_NEW_GID} != "${USERMAP_ORIG_GID}" ]]; then echo "Mapping UID and GID for paperless:paperless to $USERMAP_NEW_UID:$USERMAP_NEW_GID" usermod -u "${USERMAP_NEW_UID}" paperless - groupmod -g "${USERMAP_NEW_GID}" paperless + groupmod -o -g "${USERMAP_NEW_GID}" paperless fi } From 91272029ab0dc8c39a680694101fd74ff614c3c9 Mon Sep 17 00:00:00 2001 From: Uli <github@uli-fahrer.de> Date: Sat, 11 Jan 2020 01:11:32 +0100 Subject: [PATCH 049/101] fix highlighting skipped warning * refs https://github.com/sphinx-doc/sphinx/issues/4098 --- docs/utilities.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/utilities.rst b/docs/utilities.rst index 069251b4a..3c7e8d542 100644 --- a/docs/utilities.rst +++ b/docs/utilities.rst @@ -239,10 +239,10 @@ Basic Syntax Again we'll use the ``manage.py`` script, passing ``change_storage_type``: -.. code:: bash +.. code:: console $ /path/to/paperless/src/manage.py change_storage_type --help - usage: manage.py change_storage_type [-h] [--version] [-v {0,1,2,3}] + usage: manage.py change_storage_type [-h] [--version] [-v {0,1,2,3}] [--settings SETTINGS] [--pythonpath PYTHONPATH] [--traceback] [--no-color] [--passphrase PASSPHRASE] From e70d0c53c81cca33ce1631cb23350b58a3ea2468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Bastian=20P=C3=B6ttner?= <bastian@poettner.de> Date: Sat, 1 Feb 2020 14:22:02 +0100 Subject: [PATCH 050/101] Update paperless.conf.example Co-Authored-By: Pit <pitkley@googlemail.com> --- paperless.conf.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paperless.conf.example b/paperless.conf.example index 67e1b1c89..8f586e601 100644 --- a/paperless.conf.example +++ b/paperless.conf.example @@ -55,7 +55,7 @@ PAPERLESS_CONSUME_MAIL_PASS="" PAPERLESS_EMAIL_SECRET="" # Specify a filename format for an (optional) subdirectory and the document itself -# Use the following placefolders: +# Use the following placeholders: # * {correspondent} # * {title} # * {created} From 26b20cf62e7a6a0520f3238bf207f9a91e1484fe Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 13:25:23 +0000 Subject: [PATCH 051/101] Removed unused function many_to_list --- src/documents/models.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 0a69434e0..a5e3a6361 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -283,12 +283,6 @@ def source_filename(self): return self.filename - def many_to_list(self, field): - mylist = [] - for t in field.all(): - mylist.append(t.name) - return mylist - def many_to_dictionary(self, field): mydictionary = dict() for t in field.all(): From e79f5394fc0e6564102942327b16e593065d3e5a Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 13:26:49 +0000 Subject: [PATCH 052/101] Removed try-catch around os.makedirs and used exist_ok=True instead --- src/documents/models.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index a5e3a6361..1c7905643 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -335,13 +335,9 @@ def source_filename_new(self): if self.storage_type == self.STORAGE_TYPE_GPG: filename += ".gpg" - # Create directory for target + # Create directory for target (and ignore, if directory exists already) create_dir = self.filename_to_path(slugify(directory)) - try: - os.makedirs(create_dir) - except os.error: - # Directory existed already, ignore - pass + os.makedirs(create_dir, exist_ok=True) return filename From bcff75433c1e8274a98bc6dafde7ec3381c68ea9 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 13:52:27 +0000 Subject: [PATCH 053/101] Refactored source_filename_new into generate_source_filename and create_source_directory --- src/documents/models.py | 22 +++++++++++++++------- src/documents/tests/test_file_handling.py | 22 +++++++++++++--------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 1c7905643..e37a4fbb5 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -279,7 +279,7 @@ def __str__(self): @property def source_filename(self): if self.filename is None: - self.filename = self.source_filename_new() + self.filename = self.generate_source_filename() return self.filename @@ -298,7 +298,7 @@ def many_to_dictionary(self, field): return mydictionary - def source_filename_new(self): + def generate_source_filename(self): # Create directory name based on configured format if settings.PAPERLESS_DIRECTORY_FORMAT is not None: directory = settings.PAPERLESS_DIRECTORY_FORMAT.format( @@ -335,12 +335,17 @@ def source_filename_new(self): if self.storage_type == self.STORAGE_TYPE_GPG: filename += ".gpg" - # Create directory for target (and ignore, if directory exists already) - create_dir = self.filename_to_path(slugify(directory)) - os.makedirs(create_dir, exist_ok=True) - return filename + def create_source_directory(self): + new_filename = self.generate_source_filename() + + # Determine the full "target" path + dir_new = self.filename_to_path(os.path.dirname(new_filename)) + + # Create new path + os.makedirs(dir_new, exist_ok=True) + @property def source_path(self): return self.filename_to_path(self.source_filename) @@ -408,7 +413,7 @@ def update_filename(sender, instance, **kwargs): return # Build the new filename - new_filename = instance.source_filename_new() + new_filename = instance.generate_source_filename() # If the filename is the same, then nothing needs to be done if instance.filename is None or \ @@ -421,6 +426,9 @@ def update_filename(sender, instance, **kwargs): path_new = instance.filename_to_path(new_filename) dir_new = instance.filename_to_path(os.path.dirname(new_filename)) + # Create new path + instance.create_source_directory() + # Determine the full "current" path path_current = instance.filename_to_path(instance.filename) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index edeb1ab5e..a4d842236 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -29,16 +29,17 @@ def test_source_filename(self): @override_settings(PAPERLESS_DIRECTORY_FORMAT="") @override_settings(PAPERLESS_FILENAME_FORMAT="") - def test_source_filename_new(self): + def test_generate_source_filename(self): document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED document.save() - self.assertEqual(document.source_filename_new(), "0000001.pdf") + self.assertEqual(document.generate_source_filename(), "0000001.pdf") document.storage_type = Document.STORAGE_TYPE_GPG - self.assertEqual(document.source_filename_new(), "0000001.pdf.gpg") + self.assertEqual(document.generate_source_filename(), + "0000001.pdf.gpg") @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) @@ -52,8 +53,9 @@ def test_file_renaming(self): # Ensure that filename is properly generated tmp = document.source_filename - self.assertEqual(document.source_filename_new(), + self.assertEqual(document.generate_source_filename(), "none/none-0000001.pdf") + document.create_source_directory() Path(document.source_path).touch() # Test source_path @@ -63,7 +65,7 @@ def test_file_renaming(self): # Enable encryption and check again document.storage_type = Document.STORAGE_TYPE_GPG tmp = document.source_filename - self.assertEqual(document.source_filename_new(), + self.assertEqual(document.generate_source_filename(), "none/none-0000001.pdf.gpg") document.save() @@ -82,7 +84,7 @@ def test_file_renaming(self): "/documents/originals/none"), False) self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + "originals/test/test-0000001.pdf.gpg"), True) - self.assertEqual(document.source_filename_new(), + self.assertEqual(document.generate_source_filename(), "test/test-0000001.pdf.gpg") @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". @@ -97,8 +99,9 @@ def test_document_delete(self): # Ensure that filename is properly generated tmp = document.source_filename - self.assertEqual(document.source_filename_new(), + self.assertEqual(document.generate_source_filename(), "none/none-0000001.pdf") + document.create_source_directory() Path(document.source_path).touch() # Ensure file deletion after delete @@ -120,8 +123,9 @@ def test_directory_not_empty(self): # Ensure that filename is properly generated tmp = document.source_filename - self.assertEqual(document.source_filename_new(), + self.assertEqual(document.generate_source_filename(), "none/none-0000001.pdf") + document.create_source_directory() Path(document.source_path).touch() Path(document.source_path + "test").touch() @@ -151,4 +155,4 @@ def test_format_none(self): document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED document.save() - self.assertEqual(document.source_filename_new(), "0000001.pdf") + self.assertEqual(document.generate_source_filename(), "0000001.pdf") From ec3607cf1f5286f5691ab5dc599bf8d076014b6d Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 13:54:15 +0000 Subject: [PATCH 054/101] Removed duplicate check if instance.filename --- src/documents/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index e37a4fbb5..65beb80d4 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -416,8 +416,7 @@ def update_filename(sender, instance, **kwargs): new_filename = instance.generate_source_filename() # If the filename is the same, then nothing needs to be done - if instance.filename is None or \ - instance.filename == new_filename: + if instance.filename == new_filename: return # Check if filename needs changing From 302705325686e6ec49430d9f4dcf9e470dd79243 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 14:12:58 +0000 Subject: [PATCH 055/101] Added comment to update_document --- src/documents/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/documents/models.py b/src/documents/models.py index 65beb80d4..359960846 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -409,6 +409,7 @@ def delete_empty_directory(directory): @receiver(models.signals.m2m_changed, sender=Document.tags.through) @receiver(models.signals.post_save, sender=Document) def update_filename(sender, instance, **kwargs): + # Skip if document has not been saved yet if instance.filename is None: return From 060bdc947a9c73595befe36390b5cc096eab3512 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 14:14:13 +0000 Subject: [PATCH 056/101] Removed unnecessary check --- src/documents/models.py | 52 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 359960846..c20ecb93a 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -420,36 +420,34 @@ def update_filename(sender, instance, **kwargs): if instance.filename == new_filename: return - # Check if filename needs changing - if new_filename != instance.filename: - # Determine the full "target" path - path_new = instance.filename_to_path(new_filename) - dir_new = instance.filename_to_path(os.path.dirname(new_filename)) + # Determine the full "target" path + path_new = instance.filename_to_path(new_filename) + dir_new = instance.filename_to_path(os.path.dirname(new_filename)) - # Create new path - instance.create_source_directory() + # Create new path + instance.create_source_directory() - # Determine the full "current" path - path_current = instance.filename_to_path(instance.filename) + # Determine the full "current" path + path_current = instance.filename_to_path(instance.filename) - # Move file - try: - os.rename(path_current, path_new) - except PermissionError: - # Do not update filename in object - return - - # Delete empty directory - old_dir = os.path.dirname(instance.filename) - old_path = instance.filename_to_path(old_dir) - delete_empty_directory(old_path) - - instance.filename = new_filename - - # Save instance - # This will not cause a cascade of post_save signals, as next time - # nothing needs to be renamed - instance.save() + # Move file + try: + os.rename(path_current, path_new) + except PermissionError: + # Do not update filename in object + return + + # Delete empty directory + old_dir = os.path.dirname(instance.filename) + old_path = instance.filename_to_path(old_dir) + delete_empty_directory(old_path) + + instance.filename = new_filename + + # Save instance + # This will not cause a cascade of post_save signals, as next time + # nothing needs to be renamed + instance.save() @receiver(models.signals.post_delete, sender=Document) From a45e6c1b48f66321f81d0ecdfa9eee156c30cb66 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 14:18:33 +0000 Subject: [PATCH 057/101] Made filename_to_path a static method --- src/documents/models.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index c20ecb93a..d016c32e7 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -341,16 +341,17 @@ def create_source_directory(self): new_filename = self.generate_source_filename() # Determine the full "target" path - dir_new = self.filename_to_path(os.path.dirname(new_filename)) + dir_new = Document.filename_to_path(os.path.dirname(new_filename)) # Create new path os.makedirs(dir_new, exist_ok=True) @property def source_path(self): - return self.filename_to_path(self.source_filename) + return Document.filename_to_path(self.source_filename) - def filename_to_path(self, filename): + @staticmethod + def filename_to_path(filename): return os.path.join( settings.MEDIA_ROOT, "documents", @@ -393,7 +394,7 @@ def thumbnail_url(self): return reverse("fetch", kwargs={"kind": "thumb", "pk": self.pk}) def set_filename(self, filename): - if os.path.isfile(self.filename_to_path(filename)): + if os.path.isfile(Document.filename_to_path(filename)): self.filename = filename From 86a51c6fa56df2ac206ffad2b62f2f5d785c3877 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 20:03:20 +0000 Subject: [PATCH 058/101] Refactored delete_empty_directory into try_delete_empty_directories and implemented feature to ensure, that all created and now empty directories are really deleted --- src/documents/models.py | 37 +++++++++++++---------- src/documents/tests/test_file_handling.py | 31 +++++++++++++++++++ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index d016c32e7..58206ba11 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -294,7 +294,7 @@ def many_to_dictionary(self, field): key = t.name[:delimeter] value = t.name[delimeter+1:] - mydictionary[key] = value + mydictionary[key] = slugify(value) return mydictionary @@ -302,10 +302,10 @@ def generate_source_filename(self): # Create directory name based on configured format if settings.PAPERLESS_DIRECTORY_FORMAT is not None: directory = settings.PAPERLESS_DIRECTORY_FORMAT.format( - correspondent=self.correspondent, - title=self.title, - created=self.created, - added=self.added, + correspondent=slugify(self.correspondent), + title=slugify(self.title), + created=slugify(self.created), + added=slugify(self.added), tags=defaultdict(str, self.many_to_dictionary(self.tags))) else: @@ -314,16 +314,16 @@ def generate_source_filename(self): # Create filename based on configured format if settings.PAPERLESS_FILENAME_FORMAT is not None: filename = settings.PAPERLESS_FILENAME_FORMAT.format( - correspondent=self.correspondent, - title=self.title, - created=self.created, - added=self.added, + correspondent=slugify(self.correspondent), + title=slugify(self.title), + created=slugify(self.created), + added=slugify(self.added), tags=defaultdict(str, self.many_to_dictionary(self.tags))) else: filename = "" - path = os.path.join(slugify(directory), slugify(filename)) + path = os.path.join(directory, filename) # Always append the primary key to guarantee uniqueness of filename if len(path) > 0: @@ -398,13 +398,18 @@ def set_filename(self, filename): self.filename = filename -def delete_empty_directory(directory): - if len(os.listdir(directory)) == 0: +def try_delete_empty_directories(directory): + # Go up in the directory hierarchy and try to delete all directories + while directory != Document.filename_to_path(""): + # Try to delete the current directory try: os.rmdir(directory) except os.error: - # Directory not empty - pass + # Directory not empty, no need to go further up + return + + # Cut off actual directory and go one level up + directory, tmp = os.path.split(directory) @receiver(models.signals.m2m_changed, sender=Document.tags.through) @@ -441,7 +446,7 @@ def update_filename(sender, instance, **kwargs): # Delete empty directory old_dir = os.path.dirname(instance.filename) old_path = instance.filename_to_path(old_dir) - delete_empty_directory(old_path) + try_delete_empty_directories(old_path) instance.filename = new_filename @@ -469,7 +474,7 @@ def delete_files(sender, instance, **kwargs): # And remove the directory (if applicable) old_dir = os.path.dirname(instance.filename) old_path = instance.filename_to_path(old_dir) - delete_empty_directory(old_path) + try_delete_empty_directories(old_path) class Log(models.Model): diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index a4d842236..46f5bbc9d 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -145,6 +145,37 @@ def test_directory_not_empty(self): "/documents/originals/none/none-0000001.pdftest") os.rmdir(settings.MEDIA_ROOT + "/documents/originals/none") + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_DIRECTORY_FORMAT="{correspondent}/{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}") + def test_nested_directory_cleanup(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "none/none/none-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + # Check proper handling of files + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none/none"), True) + + document.delete() + + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + + "/documents/originals/none/none/none-0000001.pdf"), False) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none/none"), False) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none"), False) + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) @override_settings(PAPERLESS_DIRECTORY_FORMAT=None) From 6a671ebd2255530273566750567992399bc4c5e0 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 20:09:36 +0000 Subject: [PATCH 059/101] Unified PAPERLESS_DIRECTORY_FORMAT and PAPERLESS_FILENAME_FORMAT into one configuration setting --- paperless.conf.example | 3 +-- src/documents/models.py | 30 ++++++----------------- src/documents/tests/test_file_handling.py | 15 +++--------- src/paperless/settings.py | 1 - 4 files changed, 13 insertions(+), 36 deletions(-) diff --git a/paperless.conf.example b/paperless.conf.example index 8f586e601..ff96bfe20 100644 --- a/paperless.conf.example +++ b/paperless.conf.example @@ -54,7 +54,7 @@ PAPERLESS_CONSUME_MAIL_PASS="" # ignored. PAPERLESS_EMAIL_SECRET="" -# Specify a filename format for an (optional) subdirectory and the document itself +# Specify a filename format for the document (directories are supported) # Use the following placeholders: # * {correspondent} # * {title} @@ -63,7 +63,6 @@ PAPERLESS_EMAIL_SECRET="" # * {tags[FILTER]} # Uniqueness of filenames is ensured, as an incrementing counter is attached # to each filename. -#PAPERLESS_DIRECTORY_FORMAT="" #PAPERLESS_FILENAME_FORMAT="" ############################################################################### diff --git a/src/documents/models.py b/src/documents/models.py index 58206ba11..25caddebf 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -299,31 +299,17 @@ def many_to_dictionary(self, field): return mydictionary def generate_source_filename(self): - # Create directory name based on configured format - if settings.PAPERLESS_DIRECTORY_FORMAT is not None: - directory = settings.PAPERLESS_DIRECTORY_FORMAT.format( - correspondent=slugify(self.correspondent), - title=slugify(self.title), - created=slugify(self.created), - added=slugify(self.added), - tags=defaultdict(str, - self.many_to_dictionary(self.tags))) - else: - directory = "" - # Create filename based on configured format if settings.PAPERLESS_FILENAME_FORMAT is not None: - filename = settings.PAPERLESS_FILENAME_FORMAT.format( - correspondent=slugify(self.correspondent), - title=slugify(self.title), - created=slugify(self.created), - added=slugify(self.added), - tags=defaultdict(str, - self.many_to_dictionary(self.tags))) + path = settings.PAPERLESS_FILENAME_FORMAT.format( + correspondent=slugify(self.correspondent), + title=slugify(self.title), + created=slugify(self.created), + added=slugify(self.added), + tags=defaultdict(str, + self.many_to_dictionary(self.tags))) else: - filename = "" - - path = os.path.join(directory, filename) + path = "" # Always append the primary key to guarantee uniqueness of filename if len(path) > 0: diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 46f5bbc9d..30dc8fd81 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -14,7 +14,6 @@ class TestDate(TestCase): - @override_settings(PAPERLESS_DIRECTORY_FORMAT="") @override_settings(PAPERLESS_FILENAME_FORMAT="") def test_source_filename(self): document = Document() @@ -27,7 +26,6 @@ def test_source_filename(self): document.filename = "test.pdf" self.assertEqual(document.source_filename, "test.pdf") - @override_settings(PAPERLESS_DIRECTORY_FORMAT="") @override_settings(PAPERLESS_FILENAME_FORMAT="") def test_generate_source_filename(self): document = Document() @@ -43,8 +41,7 @@ def test_generate_source_filename(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_DIRECTORY_FORMAT="{correspondent}") - @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}") def test_file_renaming(self): document = Document() document.file_type = "pdf" @@ -89,8 +86,7 @@ def test_file_renaming(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_DIRECTORY_FORMAT="{correspondent}") - @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}") def test_document_delete(self): document = Document() document.file_type = "pdf" @@ -113,8 +109,7 @@ def test_document_delete(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_DIRECTORY_FORMAT="{correspondent}") - @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}") def test_directory_not_empty(self): document = Document() document.file_type = "pdf" @@ -148,8 +143,7 @@ def test_directory_not_empty(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_DIRECTORY_FORMAT="{correspondent}/{correspondent}") - @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}/{correspondent}") def test_nested_directory_cleanup(self): document = Document() document.file_type = "pdf" @@ -178,7 +172,6 @@ def test_nested_directory_cleanup(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_DIRECTORY_FORMAT=None) @override_settings(PAPERLESS_FILENAME_FORMAT=None) def test_format_none(self): document = Document() diff --git a/src/paperless/settings.py b/src/paperless/settings.py index 4a7317e02..3cadc7d2b 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -336,5 +336,4 @@ def __get_boolean(key, default="NO"): "PAPERLESS_RECENT_CORRESPONDENT_YEARS", 0)) # Specify the filename format for out files -PAPERLESS_DIRECTORY_FORMAT = os.getenv("PAPERLESS_DIRECTORY_FORMAT") PAPERLESS_FILENAME_FORMAT = os.getenv("PAPERLESS_FILENAME_FORMAT") From 05da4a559fdd17cb4bac73955a638aef749d2c33 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 20:13:05 +0000 Subject: [PATCH 060/101] Avoid TOCTOU error by rather catching an exception than checking beforehand --- src/documents/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 25caddebf..c52b6ba0a 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -450,9 +450,9 @@ def delete_files(sender, instance, **kwargs): # Remove the document old_file = instance.filename_to_path(instance.filename) - if os.path.isfile(old_file): + try: os.remove(old_file) - else: + except FileNotFoundError: logger = logging.getLogger(__name__) logger.warning("Deleted document " + str(instance.id) + " but file " + old_file + " was no longer present") From d8fda64cd074e9d954b35310b71292d3f313be0d Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 1 Feb 2020 20:58:44 +0000 Subject: [PATCH 061/101] Tags in filenames can now either be found by key (in case - or _ are used as delimeter) or by index. Added some more tests. --- paperless.conf.example | 3 +- src/documents/models.py | 26 +++++- src/documents/tests/test_file_handling.py | 107 ++++++++++++++++++++-- 3 files changed, 125 insertions(+), 11 deletions(-) diff --git a/paperless.conf.example b/paperless.conf.example index ff96bfe20..a375ae8ba 100644 --- a/paperless.conf.example +++ b/paperless.conf.example @@ -60,7 +60,8 @@ PAPERLESS_EMAIL_SECRET="" # * {title} # * {created} # * {added} -# * {tags[FILTER]} +# * {tag[KEY]} If your tags conform to key_value or key-value +# * {tags[INDEX]} If your tags are strings, select the tag by index # Uniqueness of filenames is ensured, as an incrementing counter is attached # to each filename. #PAPERLESS_FILENAME_FORMAT="" diff --git a/src/documents/models.py b/src/documents/models.py index c52b6ba0a..ae49c1518 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -283,21 +283,39 @@ def source_filename(self): return self.filename - def many_to_dictionary(self, field): + @staticmethod + def many_to_dictionary(field): + # Converts ManyToManyField to dictionary by assuming, that field + # entries contain an _ or - which will be used as a delimeter mydictionary = dict() + for t in field.all(): + # Find delimeter delimeter = t.name.find('_') + if delimeter is -1: + delimeter = t.name.find('-') + if delimeter is -1: continue key = t.name[:delimeter] value = t.name[delimeter+1:] - mydictionary[key] = slugify(value) + mydictionary[slugify(key)] = slugify(value) return mydictionary + @staticmethod + def many_to_list(field): + # Converts ManyToManyField to list + mylist = list() + + for t in field.all(): + mylist.append(slugify(t)) + + return mylist + def generate_source_filename(self): # Create filename based on configured format if settings.PAPERLESS_FILENAME_FORMAT is not None: @@ -306,8 +324,8 @@ def generate_source_filename(self): title=slugify(self.title), created=slugify(self.created), added=slugify(self.added), - tags=defaultdict(str, - self.many_to_dictionary(self.tags))) + tag=defaultdict(str, self.many_to_dictionary(self.tags)), + tags=self.many_to_list(self.tags)) else: path = "" diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 30dc8fd81..912d02573 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -9,7 +9,7 @@ from django.test import TestCase, override_settings from django.utils.text import slugify -from ..models import Document, Correspondent +from ..models import Tag, Document, Correspondent from django.conf import settings @@ -41,7 +41,8 @@ def test_generate_source_filename(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") def test_file_renaming(self): document = Document() document.file_type = "pdf" @@ -86,7 +87,8 @@ def test_file_renaming(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") def test_document_delete(self): document = Document() document.file_type = "pdf" @@ -109,7 +111,8 @@ def test_document_delete(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") def test_directory_not_empty(self): document = Document() document.file_type = "pdf" @@ -140,10 +143,101 @@ def test_directory_not_empty(self): "/documents/originals/none/none-0000001.pdftest") os.rmdir(settings.MEDIA_ROOT + "/documents/originals/none") + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{tag[type]}") + def test_tags_with_underscore(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Add tag to document + document.tags.create(name="type_demo") + document.tags.create(name="foo_bar") + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "demo-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + document.delete() + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{tag[type]}") + def test_tags_with_dash(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Add tag to document + document.tags.create(name="type-demo") + document.tags.create(name="foo-bar") + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "demo-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + document.delete() + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{tag[type]}") + def test_tags_malformed(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Add tag to document + document.tags.create(name="type:demo") + document.tags.create(name="foo:bar") + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + document.delete() + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[0]}") + def test_tags_all(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Add tag to document + document.tags.create(name="demo") + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "demo-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + document.delete() @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}/{correspondent}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}/{correspondent}") def test_nested_directory_cleanup(self): document = Document() document.file_type = "pdf" @@ -164,7 +258,8 @@ def test_nested_directory_cleanup(self): document.delete() self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + - "/documents/originals/none/none/none-0000001.pdf"), False) + "/documents/originals/none/none/none-0000001.pdf"), + False) self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + "/documents/originals/none/none"), False) self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + From 534eb7de91a6d1c3e55eb2f492a52b93b24da2d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Bastian=20P=C3=B6ttner?= <bastian@poettner.de> Date: Mon, 17 Feb 2020 20:45:43 +0100 Subject: [PATCH 062/101] Update src/documents/models.py Co-Authored-By: Pit <pitkley@googlemail.com> --- src/documents/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/documents/models.py b/src/documents/models.py index ae49c1518..fba81f697 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -413,7 +413,7 @@ def try_delete_empty_directories(directory): return # Cut off actual directory and go one level up - directory, tmp = os.path.split(directory) + directory, _ = os.path.split(directory) @receiver(models.signals.m2m_changed, sender=Document.tags.through) From 0ac93e88918df68f1ee62cfa7d272ac38a160318 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 17 Feb 2020 19:49:47 +0000 Subject: [PATCH 063/101] Ensure documents directory still exists after nested deletion --- src/documents/tests/test_file_handling.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 912d02573..c4d5f7f32 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -264,6 +264,8 @@ def test_nested_directory_cleanup(self): "/documents/originals/none/none"), False) self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + "/documents/originals/none"), False) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals"), False) @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) From 1e102efaf8a24bdf0351b3a731719fae89883e32 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 17 Feb 2020 20:58:55 +0000 Subject: [PATCH 064/101] Prevent index out of bounds for tag lists --- src/documents/models.py | 33 +++++++++++--- src/documents/tests/test_file_handling.py | 54 +++++++++++++++++++++++ 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index fba81f697..89a9f5968 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -316,16 +316,35 @@ def many_to_list(field): return mylist + @staticmethod + def fill_list(input_list, length, filler): + while len(input_list) < length: + input_list.append(slugify(filler)) + + return input_list + def generate_source_filename(self): # Create filename based on configured format if settings.PAPERLESS_FILENAME_FORMAT is not None: - path = settings.PAPERLESS_FILENAME_FORMAT.format( - correspondent=slugify(self.correspondent), - title=slugify(self.title), - created=slugify(self.created), - added=slugify(self.added), - tag=defaultdict(str, self.many_to_dictionary(self.tags)), - tags=self.many_to_list(self.tags)) + list_length = 10 + tags = self.many_to_list(self.tags) + while True: + tags = Document.fill_list(tags, list_length, None) + try: + path = settings.PAPERLESS_FILENAME_FORMAT.format( + correspondent=slugify(self.correspondent), + title=slugify(self.title), + created=slugify(self.created), + added=slugify(self.added), + tag=defaultdict(str, self.many_to_dictionary(self.tags)), + tags=tags) + break + except IndexError: + list_length *= 10 + + if list_length > 1000: + path = "" + break else: path = "" diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index c4d5f7f32..fb7f152fc 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -234,6 +234,60 @@ def test_tags_all(self): document.delete() + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[0]}") + def test_tags_out_of_bounds_0(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "none-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + document.delete() + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[10000000]}") + def test_tags_out_of_bounds_10000000(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + document.delete() + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[99]}") + def test_tags_out_of_bounds_99(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "none-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + document.delete() + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + From 1ce94348d853228f3fac3c04d074f6d276b579af Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 17 Feb 2020 20:59:17 +0000 Subject: [PATCH 065/101] Ensure filling in "none" when a tag has not been found --- src/documents/models.py | 4 +++- src/documents/tests/test_file_handling.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 89a9f5968..69d508350 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -326,6 +326,8 @@ def fill_list(input_list, length, filler): def generate_source_filename(self): # Create filename based on configured format if settings.PAPERLESS_FILENAME_FORMAT is not None: + tag = defaultdict(lambda: slugify(None), + self.many_to_dictionary(self.tags)) list_length = 10 tags = self.many_to_list(self.tags) while True: @@ -336,7 +338,7 @@ def generate_source_filename(self): title=slugify(self.title), created=slugify(self.created), added=slugify(self.added), - tag=defaultdict(str, self.many_to_dictionary(self.tags)), + tag=tag, tags=tags) break except IndexError: diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index fb7f152fc..3065948ea 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -206,7 +206,7 @@ def test_tags_malformed(self): # Ensure that filename is properly generated tmp = document.source_filename self.assertEqual(document.generate_source_filename(), - "0000001.pdf") + "none-0000001.pdf") document.create_source_directory() Path(document.source_path).touch() From 2bd4eb22924a628fcdd9f4930777a48c8018c079 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 17 Feb 2020 21:00:10 +0000 Subject: [PATCH 066/101] Fix typo in delimiter --- src/documents/models.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 69d508350..19f11336d 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -286,21 +286,21 @@ def source_filename(self): @staticmethod def many_to_dictionary(field): # Converts ManyToManyField to dictionary by assuming, that field - # entries contain an _ or - which will be used as a delimeter + # entries contain an _ or - which will be used as a delimiter mydictionary = dict() for t in field.all(): - # Find delimeter - delimeter = t.name.find('_') + # Find delimiter + delimiter = t.name.find('_') - if delimeter is -1: - delimeter = t.name.find('-') + if delimiter is -1: + delimiter = t.name.find('-') - if delimeter is -1: + if delimiter is -1: continue - key = t.name[:delimeter] - value = t.name[delimeter+1:] + key = t.name[:delimiter] + value = t.name[delimiter+1:] mydictionary[slugify(key)] = slugify(value) From 12c7b0d5f54355567f80ba6d5de1c2dc527fddd1 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 17 Feb 2020 21:02:37 +0000 Subject: [PATCH 067/101] Ensure explicit use of field name --- src/documents/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/documents/models.py b/src/documents/models.py index 19f11336d..4929ea459 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -312,7 +312,7 @@ def many_to_list(field): mylist = list() for t in field.all(): - mylist.append(slugify(t)) + mylist.append(slugify(t.name)) return mylist From 6d87bce905b45f9d54a959003f512231a5d2a6bc Mon Sep 17 00:00:00 2001 From: lawtancool <26829131+lawtancool@users.noreply.github.com> Date: Mon, 17 Feb 2020 21:46:21 -0800 Subject: [PATCH 068/101] add tzdata apk install to Dockerfile --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 30eb3a5bc..b4a32b401 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,6 +27,7 @@ RUN apk add --no-cache \ shadow \ sudo \ tesseract-ocr \ + tzdata \ unpaper && \ apk add --no-cache --virtual .build-dependencies \ g++ \ @@ -67,4 +68,4 @@ COPY data/ /usr/src/paperless/data/ COPY media/ /usr/src/paperless/media/ # Collect static files -RUN sudo -HEu paperless /usr/src/paperless/src/manage.py collectstatic --clear --no-input \ No newline at end of file +RUN sudo -HEu paperless /usr/src/paperless/src/manage.py collectstatic --clear --no-input From 177929e58b64d210b395b23c784e136b9830eb49 Mon Sep 17 00:00:00 2001 From: lawtancool <26829131+lawtancool@users.noreply.github.com> Date: Mon, 17 Feb 2020 21:48:39 -0800 Subject: [PATCH 069/101] add TZ variable to docker-compose.env.example --- docker-compose.env.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.env.example b/docker-compose.env.example index 50c1690be..7117c7dad 100644 --- a/docker-compose.env.example +++ b/docker-compose.env.example @@ -11,6 +11,8 @@ # ...are all explained in that file but can be defined here, since the Docker # installation doesn't make use of paperless.conf. +# Use this variable to set a timezone for the Paperless Docker containers. If not specified, defaults to UTC. +# TZ=America/Los_Angeles # Additional languages to install for text recognition. Note that this is # different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the From a4573a8de8d4ea123a6c8bf6049372d2a3fde26e Mon Sep 17 00:00:00 2001 From: Johann Bauer <bauerj@bauerj.eu> Date: Sat, 4 Jan 2020 00:33:24 +0100 Subject: [PATCH 070/101] Add PDF preview next to edit form --- .../admin/documents/document/change_form.html | 35 +++++++++++++++++++ src/documents/views.py | 5 ++- src/paperless/urls.py | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/documents/templates/admin/documents/document/change_form.html b/src/documents/templates/admin/documents/document/change_form.html index 88fae955d..6edcbf2b1 100644 --- a/src/documents/templates/admin/documents/document/change_form.html +++ b/src/documents/templates/admin/documents/document/change_form.html @@ -3,6 +3,10 @@ {% block content %} {{ block.super }} +<div class="side-preview"> + <h2>Preview</h2> + <object data="/fetch/preview/{{object_id}}"></object> +</div> {% if next_object %} <script type="text/javascript">//<![CDATA[ @@ -17,6 +21,37 @@ {% endblock content %} +{% block extrastyle %} +{{ block.super }} +<style> +.side-preview { + width: 100%; + height: 800px; + clear: both; +} + +.side-preview object { + height: 100%; + width: 100%; +} + +@media screen and (min-width: 1500px) { + #content-main { + width: 50%; + } + #footer { + padding: 0; + } + .side-preview { + float: right; + width: 40%; + height: 80vh; + clear: none; + } +} +</style> +{% endblock %} + {% block footer %} {{ block.super }} diff --git a/src/documents/views.py b/src/documents/views.py index f72ca22b1..aca849c70 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -69,7 +69,10 @@ def render_to_response(self, context, **response_kwargs): content_type=content_types[self.object.file_type] ) - DISPOSITION = 'inline' if settings.INLINE_DOC else 'attachment' + DISPOSITION = ( + 'inline' if settings.INLINE_DOC or self.kwargs["kind"] == 'preview' + else 'attachment' + ) response["Content-Disposition"] = '{}; filename="{}"'.format( DISPOSITION, self.object.file_name) diff --git a/src/paperless/urls.py b/src/paperless/urls.py index 8da218b4e..4ab19b06f 100644 --- a/src/paperless/urls.py +++ b/src/paperless/urls.py @@ -37,7 +37,7 @@ # File downloads url( - r"^fetch/(?P<kind>doc|thumb)/(?P<pk>\d+)$", + r"^fetch/(?P<kind>doc|thumb|preview)/(?P<pk>\d+)$", FetchView.as_view(), name="fetch" ), From 56c686da1ee75e890b982e21b12a3406ef8d7697 Mon Sep 17 00:00:00 2001 From: nxnjz <43261757+nxnjz@users.noreply.github.com> Date: Thu, 27 Feb 2020 20:05:50 +0200 Subject: [PATCH 071/101] Update paperless-webserver.service --- scripts/paperless-webserver.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/paperless-webserver.service b/scripts/paperless-webserver.service index 8fd160c4b..8ff746be2 100644 --- a/scripts/paperless-webserver.service +++ b/scripts/paperless-webserver.service @@ -1,7 +1,7 @@ [Unit] Description=Paperless webserver After=network.target -Requires=network.target +Wants=network.target [Service] User=paperless From cf4836ad07a680f5b2b251a4579c8dccaf1c5a7c Mon Sep 17 00:00:00 2001 From: Johannes Wienke <languitar@semipol.de> Date: Sat, 29 Feb 2020 17:34:39 +0100 Subject: [PATCH 072/101] Bump dependency versions Not all dependencies work well on Alpine 3.11. Thus, bump dependencies and lock again. Due to also updating the CORS packages while dependency locking, the CORS_ORIGIN_WHITELIST had to be changed to valid URIs, which are now required by the respective packages. --- Pipfile.lock | 585 +++++++++++++++++++------------------- requirements.txt | 2 +- src/paperless/settings.py | 4 +- 3 files changed, 288 insertions(+), 303 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index b1ec809e4..186cb2c83 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -28,26 +28,26 @@ ], "version": "==1.5" }, - "atomicwrites": { + "appdirs": { "hashes": [ - "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", - "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" + "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", + "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" ], - "version": "==1.3.0" + "version": "==1.4.3" }, "attrs": { "hashes": [ - "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", - "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" ], - "version": "==19.1.0" + "version": "==19.3.0" }, "babel": { "hashes": [ - "sha256:af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", - "sha256:e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28" + "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", + "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" ], - "version": "==2.7.0" + "version": "==2.8.0" }, "brotli": { "hashes": [ @@ -57,17 +57,21 @@ "sha256:1e1aa9c4d1558889f42749c8baf846007953bfd32c8209230cf1cd1f5ef33495", "sha256:2f2f4f78f29ac4a45d15b3d9fc3fd9705e0ad313a44b129f6e1d0c6916bad0e2", "sha256:3269f6de1dd150fd0cce1c158b61ff5ac06d627fd3ae9c6ea03aed26fbbff7ea", + "sha256:3f4a1f6240916c7984c7f2542786710f622992508dafee0b1714e6d340fb9ffd", "sha256:50dd9ad2a2bb12da4e9002a438672d182f98e546e99952de80280a1e1729664f", "sha256:5519a4b01b1a4f965083cbfa2ef2b9774c5a5f352341c47b50776ad109423d72", "sha256:5eb27722d320370315971c427eb8aa7cc0791f2a458840d357ac653bd0ad3a14", "sha256:5f06b4d5b6f58e5b5c220c2f23cad034dc5efa51b01fde2351ced1605bd980e2", + "sha256:71ceee286ea7ec613f1c36f1c6181864a6ca24ebb55e371276f33d6af8742834", "sha256:72848d25a5f9e736db4af4512e0c3feecc094d57d241f8f1ae959115a2c39756", "sha256:743001bca75f4a6b4454be3510feca46f9d61a0c782a9bc2bc684bdb245e279e", + "sha256:7ac98c71a15648fd11bc1f32608b6110e396121280790082e32b9a3109048bc6", "sha256:9d1c2dd27a1083fefd05b1b2f8df4a6bc2aaa6c21dd82cd41c8ae5e7c23a87f8", "sha256:a13ce9b419fe9f277c63f700efb0e444331509d1881b5610d2ba7e9080606967", "sha256:a19ef0952b9d2803df88dff07f45a6c92d5676afb9b8d69cf32232d684036d11", "sha256:ad766ca8b8c1419b71a22756b45264f45725c86133dc80a7cbe30b6b78c75620", "sha256:ad7963f261988ee0883816b6b9f206f11461c9b3cb5cfbca0c9ab5adc406d395", + "sha256:af0451e23016631a2f52925a10d738ac4a0f794ac315c30380b22efc0c90cbc6", "sha256:c16201060c5a3f8742e3deae759014251ac92f382f82bc2a41dc079ff18c3f24", "sha256:c43b202f65891861a9a336984a103de25de235f756de69e32db893156f767013", "sha256:c675c6cce4295cb1a692f3de7416aacace7314e064b94bc86e93aceefce7fd3e", @@ -78,6 +82,7 @@ "sha256:f775b07026af2b1b0b5a8b05e41571cdcf3a315a67df265d60af301656a5425b", "sha256:f969ec7f56ba9636679e69ca07fba548312ccaca37412ee823c7f413541ad7e0", "sha256:f9dc52cd70907aafb99a773b66b156f2f995c7a0d284397c487c8b71ddbef2f9", + "sha256:f9ee88bb52352588ceb811d045b5c9bb1dc38927bc150fd156244f60ff3f59f1", "sha256:fc7212e36ebeb81aebf7949c92897b622490d7c0e333a479c0395591e7994600" ], "index": "pypi", @@ -85,10 +90,10 @@ }, "certifi": { "hashes": [ - "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", - "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" ], - "version": "==2019.6.16" + "version": "==2019.11.28" }, "chardet": { "hashes": [ @@ -99,111 +104,116 @@ }, "coverage": { "hashes": [ - "sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6", - "sha256:0be0f1ed45fc0c185cfd4ecc19a1d6532d72f86a2bac9de7e24541febad72650", - "sha256:141f08ed3c4b1847015e2cd62ec06d35e67a3ac185c26f7635f4406b90afa9c5", - "sha256:19e4df788a0581238e9390c85a7a09af39c7b539b29f25c89209e6c3e371270d", - "sha256:23cc09ed395b03424d1ae30dcc292615c1372bfba7141eb85e11e50efaa6b351", - "sha256:245388cda02af78276b479f299bbf3783ef0a6a6273037d7c60dc73b8d8d7755", - "sha256:331cb5115673a20fb131dadd22f5bcaf7677ef758741312bee4937d71a14b2ef", - "sha256:386e2e4090f0bc5df274e720105c342263423e77ee8826002dcffe0c9533dbca", - "sha256:3a794ce50daee01c74a494919d5ebdc23d58873747fa0e288318728533a3e1ca", - "sha256:60851187677b24c6085248f0a0b9b98d49cba7ecc7ec60ba6b9d2e5574ac1ee9", - "sha256:63a9a5fc43b58735f65ed63d2cf43508f462dc49857da70b8980ad78d41d52fc", - "sha256:6b62544bb68106e3f00b21c8930e83e584fdca005d4fffd29bb39fb3ffa03cb5", - "sha256:6ba744056423ef8d450cf627289166da65903885272055fb4b5e113137cfa14f", - "sha256:7494b0b0274c5072bddbfd5b4a6c6f18fbbe1ab1d22a41e99cd2d00c8f96ecfe", - "sha256:826f32b9547c8091679ff292a82aca9c7b9650f9fda3e2ca6bf2ac905b7ce888", - "sha256:93715dffbcd0678057f947f496484e906bf9509f5c1c38fc9ba3922893cda5f5", - "sha256:9a334d6c83dfeadae576b4d633a71620d40d1c379129d587faa42ee3e2a85cce", - "sha256:af7ed8a8aa6957aac47b4268631fa1df984643f07ef00acd374e456364b373f5", - "sha256:bf0a7aed7f5521c7ca67febd57db473af4762b9622254291fbcbb8cd0ba5e33e", - "sha256:bf1ef9eb901113a9805287e090452c05547578eaab1b62e4ad456fcc049a9b7e", - "sha256:c0afd27bc0e307a1ffc04ca5ec010a290e49e3afbe841c5cafc5c5a80ecd81c9", - "sha256:dd579709a87092c6dbee09d1b7cfa81831040705ffa12a1b248935274aee0437", - "sha256:df6712284b2e44a065097846488f66840445eb987eb81b3cc6e4149e7b6982e1", - "sha256:e07d9f1a23e9e93ab5c62902833bf3e4b1f65502927379148b6622686223125c", - "sha256:e2ede7c1d45e65e209d6093b762e98e8318ddeff95317d07a27a2140b80cfd24", - "sha256:e4ef9c164eb55123c62411f5936b5c2e521b12356037b6e1c2617cef45523d47", - "sha256:eca2b7343524e7ba246cab8ff00cab47a2d6d54ada3b02772e908a45675722e2", - "sha256:eee64c616adeff7db37cc37da4180a3a5b6177f5c46b187894e633f088fb5b28", - "sha256:ef824cad1f980d27f26166f86856efe11eff9912c4fed97d3804820d43fa550c", - "sha256:efc89291bd5a08855829a3c522df16d856455297cf35ae827a37edac45f466a7", - "sha256:fa964bae817babece5aa2e8c1af841bebb6d0b9add8e637548809d040443fee0", - "sha256:ff37757e068ae606659c28c3bd0d923f9d29a85de79bf25b2b34b148473b5025" - ], - "version": "==4.5.4" + "sha256:15cf13a6896048d6d947bf7d222f36e4809ab926894beb748fc9caa14605d9c3", + "sha256:1daa3eceed220f9fdb80d5ff950dd95112cd27f70d004c7918ca6dfc6c47054c", + "sha256:1e44a022500d944d42f94df76727ba3fc0a5c0b672c358b61067abb88caee7a0", + "sha256:25dbf1110d70bab68a74b4b9d74f30e99b177cde3388e07cc7272f2168bd1477", + "sha256:3230d1003eec018ad4a472d254991e34241e0bbd513e97a29727c7c2f637bd2a", + "sha256:3dbb72eaeea5763676a1a1efd9b427a048c97c39ed92e13336e726117d0b72bf", + "sha256:5012d3b8d5a500834783689a5d2292fe06ec75dc86ee1ccdad04b6f5bf231691", + "sha256:51bc7710b13a2ae0c726f69756cf7ffd4362f4ac36546e243136187cfcc8aa73", + "sha256:527b4f316e6bf7755082a783726da20671a0cc388b786a64417780b90565b987", + "sha256:722e4557c8039aad9592c6a4213db75da08c2cd9945320220634f637251c3894", + "sha256:76e2057e8ffba5472fd28a3a010431fd9e928885ff480cb278877c6e9943cc2e", + "sha256:77afca04240c40450c331fa796b3eab6f1e15c5ecf8bf2b8bee9706cd5452fef", + "sha256:7afad9835e7a651d3551eab18cbc0fdb888f0a6136169fbef0662d9cdc9987cf", + "sha256:9bea19ac2f08672636350f203db89382121c9c2ade85d945953ef3c8cf9d2a68", + "sha256:a8b8ac7876bc3598e43e2603f772d2353d9931709345ad6c1149009fd1bc81b8", + "sha256:b0840b45187699affd4c6588286d429cd79a99d509fe3de0f209594669bb0954", + "sha256:b26aaf69713e5674efbde4d728fb7124e429c9466aeaf5f4a7e9e699b12c9fe2", + "sha256:b63dd43f455ba878e5e9f80ba4f748c0a2156dde6e0e6e690310e24d6e8caf40", + "sha256:be18f4ae5a9e46edae3f329de2191747966a34a3d93046dbdf897319923923bc", + "sha256:c312e57847db2526bc92b9bfa78266bfbaabac3fdcd751df4d062cd4c23e46dc", + "sha256:c60097190fe9dc2b329a0eb03393e2e0829156a589bd732e70794c0dd804258e", + "sha256:c62a2143e1313944bf4a5ab34fd3b4be15367a02e9478b0ce800cb510e3bbb9d", + "sha256:cc1109f54a14d940b8512ee9f1c3975c181bbb200306c6d8b87d93376538782f", + "sha256:cd60f507c125ac0ad83f05803063bed27e50fa903b9c2cfee3f8a6867ca600fc", + "sha256:d513cc3db248e566e07a0da99c230aca3556d9b09ed02f420664e2da97eac301", + "sha256:d649dc0bcace6fcdb446ae02b98798a856593b19b637c1b9af8edadf2b150bea", + "sha256:d7008a6796095a79544f4da1ee49418901961c97ca9e9d44904205ff7d6aa8cb", + "sha256:da93027835164b8223e8e5af2cf902a4c80ed93cb0909417234f4a9df3bcd9af", + "sha256:e69215621707119c6baf99bda014a45b999d37602cb7043d943c76a59b05bf52", + "sha256:ea9525e0fef2de9208250d6c5aeeee0138921057cd67fcef90fbed49c4d62d37", + "sha256:fca1669d464f0c9831fd10be2eef6b86f5ebd76c724d1e0706ebdff86bb4adf0" + ], + "version": "==5.0.3" }, "coveralls": { "hashes": [ - "sha256:ab638e88d38916a6cedbf80a9cd8992d5fa55c77ab755e262e00b36792b7cd6d", - "sha256:b2388747e2529fa4c669fb1e3e2756e4e07b6ee56c7d9fce05f35ccccc913aa0" + "sha256:4b6bfc2a2a77b890f556bc631e35ba1ac21193c356393b66c84465c06218e135", + "sha256:67188c7ec630c5f708c31552f2bcdac4580e172219897c4136504f14b823132f" ], "index": "pypi", - "version": "==1.5.1" + "version": "==1.11.1" }, "dateparser": { "hashes": [ - "sha256:940828183c937bcec530753211b70f673c0a9aab831e43273489b310538dff86", - "sha256:b452ef8b36cd78ae86a50721794bc674aa3994e19b570f7ba92810f4e0a2ae03" + "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665", + "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b" ], "index": "pypi", - "version": "==0.7.0" + "version": "==0.7.2" + }, + "distlib": { + "hashes": [ + "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21" + ], + "version": "==0.3.0" }, "django": { "hashes": [ - "sha256:0292a7ad7d8ffc9cfc6a77f043d2e81f5bbc360c0c4a1686e130ef3432437d23", - "sha256:e89f613e3c1f7ff245ffee3560472f9fa9c07060b11f65e1de3cb763f8dcd4b9" + "sha256:665457d4146bbd34ae9d2970fa3b37082d7b225b0671bfd24c337458f229db78", + "sha256:bde46d4dbc410678e89bc95ea5d312dd6eb4c37d0fa0e19c9415cad94addf22f" ], "index": "pypi", - "version": "==2.0.10" + "version": "==2.0.13" }, "django-cors-headers": { "hashes": [ - "sha256:5545009c9b233ea7e70da7dbab7cb1c12afa01279895086f98ec243d7eab46fa", - "sha256:c4c2ee97139d18541a1be7d96fe337d1694623816d83f53cb7c00da9b94acae1" + "sha256:a5960addecc04527ab26617e51b8ed42f0adab4594b24bb0f3c33e2bd3857c3f", + "sha256:a785b5f446f6635810776d9f5f5d23e6a2a2f728ea982648370afaf0dfdf2627" ], "index": "pypi", - "version": "==2.4.0" + "version": "==3.2.1" }, "django-crispy-forms": { "hashes": [ - "sha256:5952bab971110d0b86c278132dae0aa095beee8f723e625c3d3fa28888f1675f", - "sha256:705ededc554ad8736157c666681165fe22ead2dec0d5446d65fc9dd976a5a876" + "sha256:0afc0ba730f52a13c02bfbd0e1423af4577a337d73a8a0ef96f2cbbc5f345ffa", + "sha256:2db711ce31f6f9ef42c16829cc3636e3819f97c1b22a3b706afed679bc417e88" ], "index": "pypi", - "version": "==1.7.2" + "version": "==1.8.1" }, "django-extensions": { "hashes": [ - "sha256:8317a3fe479b1ba3e3a04ecf33fb8d6ccf09bb18f30eab64e34c40a593741d26", - "sha256:a76a61566f1c8d96acc7bcf765080b8e91367a25a2c6f8c5bddd574493839180" + "sha256:1a03c4e8bade575f8c2be6c76456f8a2be3f9b02ab9f47d3535afa9562dc0493", + "sha256:2699cc1d6fb4bd393c0b5832fea4bc685f2ace5800b3c9ff222b2080f161ac04" ], "index": "pypi", - "version": "==2.1.4" + "version": "==2.2.8" }, "django-filter": { "hashes": [ - "sha256:3dafb7d2810790498895c22a1f31b2375795910680ac9c1432821cbedb1e176d", - "sha256:a3014de317bef0cd43075a0f08dfa1d319a7ccc5733c3901fb860da70b0dda68" + "sha256:558c727bce3ffa89c4a7a0b13bc8976745d63e5fd576b3a9a851650ef11c401b", + "sha256:c3deb57f0dd7ff94d7dce52a047516822013e2b441bed472b722a317658cfd14" ], "index": "pypi", - "version": "==2.1.0" + "version": "==2.2.0" }, "djangoql": { "hashes": [ - "sha256:7c488ec4e3362e5389ba3c1169d1ff9a27c4222601f32c6dbf6130ce04330d76" + "sha256:366293d7d4e416f9f7d6e2b98775c2129222fbb4dc660f3e6c7b9e35a3cf3fce" ], "index": "pypi", - "version": "==0.12.3" + "version": "==0.13.1" }, "djangorestframework": { "hashes": [ - "sha256:79c6efbb2514bc50cf25906d7c0a5cfead714c7af667ff4bd110312cd380ae66", - "sha256:a4138613b67e3a223be6c97f53b13d759c5b90d2b433bad670b8ebf95402075f" + "sha256:05809fc66e1c997fd9a32ea5730d9f4ba28b109b9da71fccfa5ff241201fd0a4", + "sha256:e782087823c47a26826ee5b6fa0c542968219263fb3976ec3c31edab23a4001f" ], "index": "pypi", - "version": "==3.9.1" + "version": "==3.11.0" }, "docopt": { "hashes": [ @@ -213,33 +223,32 @@ }, "docutils": { "hashes": [ - "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", - "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", - "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99" + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" ], - "version": "==0.15.2" + "version": "==0.16" }, "execnet": { "hashes": [ - "sha256:64dcdc248d007060f6f6500e7c79a4f87ee692063e3ec51e9bebf30ef2ea21d7", - "sha256:dfd10a5663f94d1235e6fbee86bc53e2f89b6f15e031e7e6d9e4bb345bcd7e52" + "sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50", + "sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547" ], - "version": "==1.6.1" + "version": "==1.7.1" }, "factory-boy": { "hashes": [ - "sha256:6f25cc4761ac109efd503f096e2ad99421b1159f01a29dbb917359dcd68e08ca", - "sha256:d552cb872b310ae78bd7429bf318e42e1e903b1a109e899a523293dfa762ea4f" + "sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee", + "sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370" ], "index": "pypi", - "version": "==2.11.1" + "version": "==2.12.0" }, "faker": { "hashes": [ - "sha256:96ad7902706f2409a2d0c3de5132f69b413555a419bacec99d3f16e657895b47", - "sha256:b3bb64aff9571510de6812df45122b633dbc6227e870edae3ed9430f94698521" + "sha256:047d4d1791bfb3756264da670d99df13d799bb36e7d88774b1585a82d05dbaec", + "sha256:1b1a58961683b30c574520d0c739c4443e0ef6a185c04382e8cc888273dbebed" ], - "version": "==2.0.0" + "version": "==4.0.0" }, "filelock": { "hashes": [ @@ -268,11 +277,11 @@ }, "gunicorn": { "hashes": [ - "sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471", - "sha256:fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3" + "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626", + "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c" ], "index": "pypi", - "version": "==19.9.0" + "version": "==20.0.4" }, "idna": { "hashes": [ @@ -283,31 +292,24 @@ }, "imagesize": { "hashes": [ - "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", - "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5" + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" ], - "version": "==1.1.0" - }, - "importlib-metadata": { - "hashes": [ - "sha256:23d3d873e008a513952355379d93cbcab874c58f4f034ff657c7a87422fa64e8", - "sha256:80d2de76188eabfbfcf27e6a37342c2827801e59c4cc14b0371c56fed43820e3" - ], - "version": "==0.19" + "version": "==1.2.0" }, "inotify-simple": { "hashes": [ - "sha256:fc2c10dd73278a1027d0663f2db51240af5946390f363a154361406ebdddd8dd" + "sha256:db69f2d75603e0e8f72e734854ac445beb60ed38922bc97b7f7a522795ca4c8c" ], "index": "pypi", - "version": "==1.1.8" + "version": "==1.2.1" }, "jinja2": { "hashes": [ - "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", - "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" + "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", + "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" ], - "version": "==2.10.1" + "version": "==2.11.1" }, "langdetect": { "hashes": [ @@ -322,13 +324,16 @@ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", @@ -345,73 +350,67 @@ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" ], "version": "==1.1.1" }, "more-itertools": { "hashes": [ - "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", - "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" + "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c", + "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507" ], - "version": "==7.2.0" + "version": "==8.2.0" }, "packaging": { "hashes": [ - "sha256:a7ac867b97fdc07ee80a8058fe4435ccd274ecc3b0ed61d852d7d53055528cf9", - "sha256:c491ca87294da7cc01902edbe30a5bc6c4c28172b5138ab4e4aa1b9d7bfaeafe" + "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73", + "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334" ], - "version": "==19.1" + "version": "==20.1" }, "pdftotext": { "hashes": [ - "sha256:e3ad11efe0aa22cbfc46aa1296b2ea5a52ad208b778288311f2801adef178ccb" + "sha256:d37864049581fb13cdcf7b23d4ea23dac7ca2e9c646e8ecac1a39275ab1cae03" ], "index": "pypi", - "version": "==2.1.1" + "version": "==2.1.4" }, "pillow": { "hashes": [ - "sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e", - "sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7", - "sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a", - "sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3", - "sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1", - "sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1", - "sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7", - "sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1", - "sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3", - "sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055", - "sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf", - "sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f", - "sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f", - "sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239", - "sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe", - "sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c", - "sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697", - "sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494", - "sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356", - "sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6", - "sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000", - "sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f", - "sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c", - "sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca", - "sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8", - "sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3", - "sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad", - "sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9", - "sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc", - "sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e" - ], - "index": "pypi", - "version": "==5.4.1" + "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be", + "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946", + "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837", + "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f", + "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00", + "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d", + "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533", + "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a", + "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358", + "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda", + "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435", + "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2", + "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313", + "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff", + "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317", + "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2", + "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614", + "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0", + "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386", + "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9", + "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636", + "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865" + ], + "index": "pypi", + "version": "==7.0.0" }, "pluggy": { "hashes": [ - "sha256:0825a152ac059776623854c1543d65a4ad408eb3d33ee114dff91e57ec6ae6fc", - "sha256:b9817417e95936bf75d85d3f8767f7df6cdde751fc40aed3bb3074cbcb77757c" + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" ], - "version": "==0.12.0" + "version": "==0.13.1" }, "ply": { "hashes": [ @@ -422,99 +421,82 @@ }, "psycopg2": { "hashes": [ - "sha256:02445ebbb3a11a3fe8202c413d5e6faf38bb75b4e336203ee144ca2c46529f94", - "sha256:0e9873e60f98f0c52339abf8f0339d1e22bfe5aae0bcf7aabd40c055175035ec", - "sha256:1148a5eb29073280bf9057c7fc45468592c1bb75a28f6df1591adb93c8cb63d0", - "sha256:259a8324e109d4922b0fcd046e223e289830e2568d6f4132a3702439e5fd532b", - "sha256:28dffa9ed4595429e61bacac41d3f9671bb613d1442ff43bcbec63d4f73ed5e8", - "sha256:314a74302d4737a3865d40ea50e430ce1543c921ba10f39d562e807cfe2edf2a", - "sha256:36b60201b6d215d7658a71493fdf6bd5e60ad9a0cffed39906627ff9f4f3afd3", - "sha256:3f9d532bce54c4234161176ff3b8688ff337575ca441ea27597e112dfcd0ee0c", - "sha256:5d222983847b40af989ad96c07fc3f07e47925e463baa5de716be8f805b41d9b", - "sha256:6757a6d2fc58f7d8f5d471ad180a0bd7b4dd3c7d681f051504fbea7ae29c8d6f", - "sha256:6a0e0f1e74edb0ab57d89680e59e7bfefad2bfbdf7c80eb38304d897d43674bb", - "sha256:6ca703ccdf734e886a1cf53eb702261110f6a8b0ed74bcad15f1399f74d3f189", - "sha256:8513b953d8f443c446aa79a4cc8a898bd415fc5e29349054f03a7d696d495542", - "sha256:9262a5ce2038570cb81b4d6413720484cb1bc52c064b2f36228d735b1f98b794", - "sha256:97441f851d862a0c844d981cbee7ee62566c322ebb3d68f86d66aa99d483985b", - "sha256:a07feade155eb8e69b54dd6774cf6acf2d936660c61d8123b8b6b1f9247b67d6", - "sha256:a9b9c02c91b1e3ec1f1886b2d0a90a0ea07cc529cb7e6e472b556bc20ce658f3", - "sha256:ae88216f94728d691b945983140bf40d51a1ff6c7fe57def93949bf9339ed54a", - "sha256:b360ffd17659491f1a6ad7c928350e229c7b7bd83a2b922b6ee541245c7a776f", - "sha256:b4221957ceccf14b2abdabef42d806e791350be10e21b260d7c9ce49012cc19e", - "sha256:b90758e49d5e6b152a460d10b92f8a6ccf318fcc0ee814dcf53f3a6fc5328789", - "sha256:c669ea986190ed05fb289d0c100cc88064351f2b85177cbfd3564c4f4847d18c", - "sha256:d1b61999d15c79cf7f4f7cc9021477aef35277fc52452cf50fd13b713c84424d", - "sha256:de7bb043d1adaaf46e38d47e7a5f703bb3dab01376111e522b07d25e1a79c1e1", - "sha256:e393568e288d884b94d263f2669215197840d097c7e5b0acd1a51c1ea7d1aba8", - "sha256:ed7e0849337bd37d89f2c2b0216a0de863399ee5d363d31b1e5330a99044737b", - "sha256:f153f71c3164665d269a5d03c7fa76ba675c7a8de9dc09a4e2c2cdc9936a7b41", - "sha256:f1fb5a8427af099beb7f65093cbdb52e021b8e6dbdfaf020402a623f4181baf5", - "sha256:f36b333e9f86a2fba960c72b90c34be6ca71819e300f7b1fc3d2b0f0b2c546cd", - "sha256:f4526d078aedd5187d0508aa5f9a01eae6a48a470ed678406da94b4cd6524b7e" - ], - "index": "pypi", - "version": "==2.7.7" + "sha256:4212ca404c4445dc5746c0d68db27d2cbfb87b523fe233dc84ecd24062e35677", + "sha256:47fc642bf6f427805daf52d6e52619fe0637648fe27017062d898f3bf891419d", + "sha256:72772181d9bad1fa349792a1e7384dde56742c14af2b9986013eb94a240f005b", + "sha256:8396be6e5ff844282d4d49b81631772f80dabae5658d432202faf101f5283b7c", + "sha256:893c11064b347b24ecdd277a094413e1954f8a4e8cdaf7ffbe7ca3db87c103f0", + "sha256:92a07dfd4d7c325dd177548c4134052d4842222833576c8391aab6f74038fc3f", + "sha256:965c4c93e33e6984d8031f74e51227bd755376a9df6993774fd5b6fb3288b1f4", + "sha256:9ab75e0b2820880ae24b7136c4d230383e07db014456a476d096591172569c38", + "sha256:b0845e3bdd4aa18dc2f9b6fb78fbd3d9d371ad167fd6d1b7ad01c0a6cdad4fc6", + "sha256:dca2d7203f0dfce8ea4b3efd668f8ea65cd2b35112638e488a4c12594015f67b", + "sha256:ed686e5926929887e2c7ae0a700e32c6129abb798b4ad2b846e933de21508151", + "sha256:ef6df7e14698e79c59c7ee7cf94cd62e5b869db369ed4b1b8f7b729ea825712a", + "sha256:f898e5cc0a662a9e12bde6f931263a1bbd350cfb18e1d5336a12927851825bb6" + ], + "index": "pypi", + "version": "==2.8.4" }, "py": { "hashes": [ - "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", - "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" + "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", + "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" ], - "version": "==1.8.0" + "version": "==1.8.1" }, "pycodestyle": { "hashes": [ - "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", - "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" ], "index": "pypi", - "version": "==2.4.0" + "version": "==2.5.0" }, "pygments": { "hashes": [ - "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", - "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297" + "sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b", + "sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe" ], - "version": "==2.4.2" + "version": "==2.5.2" }, "pyocr": { "hashes": [ - "sha256:b6ba6263fd92da56627dff6d263d991a2246aacd117d1788f11b93f419ca395f" + "sha256:fa15adc7e1cf0d345a2990495fe125a947c6e09a60ddba0256a1c14b2e603179" ], "index": "pypi", - "version": "==0.5.3" + "version": "==0.7.2" }, "pyparsing": { "hashes": [ - "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", - "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" + "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", + "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" ], - "version": "==2.4.2" + "version": "==2.4.6" }, "pytest": { "hashes": [ - "sha256:41568ea7ecb4a68d7f63837cf65b92ce8d0105e43196ff2b26622995bb3dc4b2", - "sha256:c3c573a29d7c9547fb90217ece8a8843aa0c1328a797e200290dc3d0b4b823be" + "sha256:0d5fe9189a148acc3c3eb2ac8e1ac0742cb7618c084f3d228baaec0c254b318d", + "sha256:ff615c761e25eb25df19edddc0b970302d2a9091fbce0e7213298d85fb61fef6" ], "index": "pypi", - "version": "==4.1.1" + "version": "==5.3.5" }, "pytest-cov": { "hashes": [ - "sha256:0ab664b25c6aa9716cbf203b17ddb301932383046082c081b9848a0edf5add33", - "sha256:230ef817450ab0699c6cc3c9c8f7a829c34674456f2ed8df1fe1d39780f7c87f" + "sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b", + "sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626" ], "index": "pypi", - "version": "==2.6.1" + "version": "==2.8.1" }, "pytest-django": { "hashes": [ - "sha256:1a5d33be930e3172fa238643a380414dc369fe8fa4b3c3de25e59ed142950736", - "sha256:e88e471d3d0f9acfb6293bb03d0ee8a33ed978734e92ea6b5312163a6c9e87cc" + "sha256:456fa6854d04ee625d6bbb8b38ca2259e7040a6f93333bfe8bc8159b7e987203", + "sha256:489b904f695f9fb880ce591cf5a4979880afb467763b1f180c07574554bdfd26" ], "index": "pypi", - "version": "==3.4.5" + "version": "==3.8.0" }, "pytest-env": { "hashes": [ @@ -525,10 +507,10 @@ }, "pytest-forked": { "hashes": [ - "sha256:5fe33fbd07d7b1302c95310803a5e5726a4ff7f19d5a542b7ce57c76fed8135f", - "sha256:d352aaced2ebd54d42a65825722cb433004b4446ab5d2044851d9cc7a00c9e38" + "sha256:1805699ed9c9e60cb7a8179b8d4fa2b8898098e82d229b0825d8095f0f261100", + "sha256:1ae25dba8ee2e56fb47311c9638f9e58552691da87e82d25b0ce0e4bf52b7d87" ], - "version": "==1.0.2" + "version": "==1.1.3" }, "pytest-sugar": { "hashes": [ @@ -540,35 +522,35 @@ }, "pytest-xdist": { "hashes": [ - "sha256:107e9db0ee30ead02ca93e7d6d4846675f1b2142234f0eb1cd4d76739cd9ae6f", - "sha256:5795f665e112520fa5beab736ad957e7f36ce7d44210f4004be9d99f86529d97" + "sha256:0f46020d3d9619e6d17a65b5b989c1ebbb58fc7b1da8fb126d70f4bac4dfeed1", + "sha256:7dc0d027d258cd0defc618fb97055fbd1002735ca7a6d17037018cf870e24011" ], "index": "pypi", - "version": "==1.26.0" + "version": "==1.31.0" }, "python-dateutil": { "hashes": [ - "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", - "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], "index": "pypi", - "version": "==2.7.5" + "version": "==2.8.1" }, "python-dotenv": { "hashes": [ - "sha256:a84569d0e00d178bc5b957f7ff208bf49287cbf61857c31c258c4a91f571527b", - "sha256:c9b1ddd3cdbe75c7d462cb84674d87130f4b948f090f02c7d7144779afb99ae0" + "sha256:8429f459fc041237d98c9ff32e1938e7e5535b5ff24388876315a098027c3a57", + "sha256:ca9f3debf2262170d6f46571ce4d6ca1add60bb93b69c3a29dcb3d1a00a65c93" ], "index": "pypi", - "version": "==0.10.1" + "version": "==0.11.0" }, "python-gnupg": { "hashes": [ - "sha256:45daf020b370bda13a1429c859fcdff0b766c0576844211446f9266cae97fb0e", - "sha256:85c231850a0275c9722f06e34b45a22510b83a6a6e88f93b5ae32ba04c95056c" + "sha256:3353e59949cd2c15efbf1fca45e347d8a22f4bed0d93e9b89b2657bda19cec05", + "sha256:c095a41f310ad7a4fd393406660ac9bd6c175ccaa0f072f9c18f33be8130a27a" ], "index": "pypi", - "version": "==0.4.4" + "version": "==0.4.5" }, "python-levenshtein": { "hashes": [ @@ -578,27 +560,37 @@ }, "pytz": { "hashes": [ - "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", - "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" + "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", + "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" ], "index": "pypi", - "version": "==2018.9" + "version": "==2019.3" }, "regex": { "hashes": [ - "sha256:1c70ccb8bf4ded0cbe53092e9f56dcc9d6b0efcf6e80b6ef9b0ece8a557d6635", - "sha256:2948310c01535ccb29bb600dd033b07b91f36e471953889b7f3a1e66b39d0c19", - "sha256:2ab13db0411cb308aa590d33c909ea4efeced40188d8a4a7d3d5970657fe73bc", - "sha256:38e6486c7e14683cd1b17a4218760f0ea4c015633cf1b06f7c190fb882a51ba7", - "sha256:80dde4ff10b73b823da451687363cac93dd3549e059d2dc19b72a02d048ba5aa", - "sha256:84daedefaa56320765e9c4d43912226d324ef3cc929f4d75fa95f8c579a08211", - "sha256:b98e5876ca1e63b41c4aa38d7d5cc04a736415d4e240e9ae7ebc4f780083c7d5", - "sha256:ca4f47131af28ef168ff7c80d4b4cad019cb4cabb5fa26143f43aa3dbd60389c", - "sha256:cf7838110d3052d359da527372666429b9485ab739286aa1a11ed482f037a88c", - "sha256:dd4e8924915fa748e128864352875d3d0be5f4597ab1b1d475988b8e3da10dd7", - "sha256:f2c65530255e4010a5029eb11138f5ecd5aa70363f57a3444d83b3253b0891be" - ], - "version": "==2019.6.8" + "sha256:07b39bf943d3d2fe63d46281d8504f8df0ff3fe4c57e13d1656737950e53e525", + "sha256:0932941cdfb3afcbc26cc3bcf7c3f3d73d5a9b9c56955d432dbf8bbc147d4c5b", + "sha256:0e182d2f097ea8549a249040922fa2b92ae28be4be4895933e369a525ba36576", + "sha256:10671601ee06cf4dc1bc0b4805309040bb34c9af423c12c379c83d7895622bb5", + "sha256:23e2c2c0ff50f44877f64780b815b8fd2e003cda9ce817a7fd00dea5600c84a0", + "sha256:26ff99c980f53b3191d8931b199b29d6787c059f2e029b2b0c694343b1708c35", + "sha256:27429b8d74ba683484a06b260b7bb00f312e7c757792628ea251afdbf1434003", + "sha256:3e77409b678b21a056415da3a56abfd7c3ad03da71f3051bbcdb68cf44d3c34d", + "sha256:4e8f02d3d72ca94efc8396f8036c0d3bcc812aefc28ec70f35bb888c74a25161", + "sha256:4eae742636aec40cf7ab98171ab9400393360b97e8f9da67b1867a9ee0889b26", + "sha256:6a6ae17bf8f2d82d1e8858a47757ce389b880083c4ff2498dba17c56e6c103b9", + "sha256:6a6ba91b94427cd49cd27764679024b14a96874e0dc638ae6bdd4b1a3ce97be1", + "sha256:7bcd322935377abcc79bfe5b63c44abd0b29387f267791d566bbb566edfdd146", + "sha256:98b8ed7bb2155e2cbb8b76f627b2fd12cf4b22ab6e14873e8641f266e0fb6d8f", + "sha256:bd25bb7980917e4e70ccccd7e3b5740614f1c408a642c245019cff9d7d1b6149", + "sha256:d0f424328f9822b0323b3b6f2e4b9c90960b24743d220763c7f07071e0778351", + "sha256:d58e4606da2a41659c84baeb3cfa2e4c87a74cec89a1e7c56bee4b956f9d7461", + "sha256:e3cd21cc2840ca67de0bbe4071f79f031c81418deb544ceda93ad75ca1ee9f7b", + "sha256:e6c02171d62ed6972ca8631f6f34fa3281d51db8b326ee397b9c83093a6b7242", + "sha256:e7c7661f7276507bce416eaae22040fd91ca471b5b33c13f8ff21137ed6f248c", + "sha256:ecc6de77df3ef68fee966bb8cb4e067e84d4d1f397d0ef6fce46913663540d77" + ], + "version": "==2020.1.8" }, "requests": { "hashes": [ @@ -609,24 +601,25 @@ }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.12.0" + "version": "==1.14.0" }, "snowballstemmer": { "hashes": [ - "sha256:9f3b9ffe0809d174f7047e121431acf99c89a7040f0ca84f94ba53a498e6d0c9" + "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", + "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" ], - "version": "==1.9.0" + "version": "==2.0.0" }, "sphinx": { "hashes": [ - "sha256:429e3172466df289f0f742471d7e30ba3ee11f3b5aecd9a840480d03f14bcfe5", - "sha256:c4cb17ba44acffae3d3209646b6baec1e215cad3065e852c68cc569d4df1b9f8" + "sha256:5024a67f065fe60d9db2005580074d81f22a02dd8f00a5b1ec3d5f4d42bc88d8", + "sha256:f929b72e0cfe45fa581b8964d54457117863a6a6c9369ecc1a65b8827abd3bf2" ], "index": "pypi", - "version": "==1.8.3" + "version": "==2.4.1" }, "sphinxcontrib-applehelp": { "hashes": [ @@ -678,10 +671,10 @@ }, "text-unidecode": { "hashes": [ - "sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d", - "sha256:801e38bd550b943563660a91de8d4b6fa5df60a542be9093f7abf819f86050cc" + "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", + "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" ], - "version": "==1.2" + "version": "==1.3" }, "toml": { "hashes": [ @@ -692,11 +685,11 @@ }, "tox": { "hashes": [ - "sha256:04f8f1aa05de8e76d7a266ccd14e0d665d429977cd42123bc38efa9b59964e9e", - "sha256:25ef928babe88c71e3ed3af0c464d1160b01fca2dd1870a5bb26c2dea61a17fc" + "sha256:5c45d08f1dcc9bc97cdea3e5a69c8f4ad042cc37cbe6cf53e126f4a9005b7d3b", + "sha256:73e2ade68cd71a2765ee739ecc27c8c92e9b9c09acbad0f2c5307b20214e0d13" ], "index": "pypi", - "version": "==3.7.0" + "version": "==3.14.4" }, "tzlocal": { "hashes": [ @@ -707,39 +700,32 @@ }, "urllib3": { "hashes": [ - "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", - "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", + "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" ], - "version": "==1.25.3" + "version": "==1.25.8" }, "virtualenv": { "hashes": [ - "sha256:6cb2e4c18d22dbbe283d0a0c31bb7d90771a606b2cb3415323eea008eaee6a9d", - "sha256:909fe0d3f7c9151b2df0a2cb53e55bdb7b0d61469353ff7a49fd47b0f0ab9285" + "sha256:08f3623597ce73b85d6854fb26608a6f39ee9d055c81178dc6583803797f8994", + "sha256:de2cbdd5926c48d7b84e0300dea9e8f276f61d186e8e49223d71d91250fbaebd" ], - "version": "==16.7.2" + "version": "==20.0.4" }, "wcwidth": { "hashes": [ - "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", - "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603", + "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8" ], - "version": "==0.1.7" + "version": "==0.1.8" }, "whitenoise": { "hashes": [ - "sha256:59d880d25d0e90bcc6554fe0504a11195bd2e59b3d690b6fb42a8040d4e67ef5", - "sha256:c9b7c47fdc1dba4d37bf2787a01a844dc7a521e174fcd22a2d429e0be65e1782" + "sha256:0f9137f74bd95fa54329ace88d8dc695fbe895369a632e35f7a136e003e41d73", + "sha256:62556265ec1011bd87113fb81b7516f52688887b7a010ee899ff1fd18fd22700" ], "index": "pypi", - "version": "==4.1.3" - }, - "zipp": { - "hashes": [ - "sha256:4970c3758f4e89a7857a973b1e2a5d75bcdc47794442f2e2dd4fe8e0466e809a", - "sha256:8a5712cfd3bb4248015eb3b0b3c54a5f6ee3f2425963ef2a0125b8bc40aafaec" - ], - "version": "==0.5.2" + "version": "==5.0.1" } }, "develop": { @@ -752,18 +738,18 @@ }, "decorator": { "hashes": [ - "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", - "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6" + "sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce", + "sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d" ], - "version": "==4.4.0" + "version": "==4.4.1" }, "ipython": { "hashes": [ - "sha256:6a9496209b76463f1dec126ab928919aaf1f55b38beb9219af3fe202f6bbdd12", - "sha256:f69932b1e806b38a7818d9a1e918e5821b685715040b48e59c657b3c7961b742" + "sha256:d9459e7237e2e5858738ff9c3e26504b79899b58a6d49e574d352493d80684c6", + "sha256:f6689108b1734501d3b59c84427259fd5ac5141afe2e846cfa8598eb811886c9" ], "index": "pypi", - "version": "==7.2.0" + "version": "==7.12.0" }, "ipython-genutils": { "hashes": [ @@ -774,25 +760,25 @@ }, "jedi": { "hashes": [ - "sha256:53c850f1a7d3cfcd306cc513e2450a54bdf5cacd7604b74e42dd1f0758eaaf36", - "sha256:e07457174ef7cb2342ff94fa56484fe41cec7ef69b0059f01d3f812379cb6f7c" + "sha256:b4f4052551025c6b0b0b193b29a6ff7bdb74c52450631206c262aef9f7159ad2", + "sha256:d5c871cb9360b414f981e7072c52c33258d598305280fef91c6cae34739d65d5" ], - "version": "==0.14.1" + "version": "==0.16.0" }, "parso": { "hashes": [ - "sha256:63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc", - "sha256:666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c" + "sha256:56b2105a80e9c4df49de85e125feb6be69f49920e121406f15e7acde6c9dfc57", + "sha256:951af01f61e6dccd04159042a0706a31ad437864ec6e25d0d7a96a9fbb9b0095" ], - "version": "==0.5.1" + "version": "==0.6.1" }, "pexpect": { "hashes": [ - "sha256:2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1", - "sha256:9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb" + "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", + "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" ], "markers": "sys_platform != 'win32'", - "version": "==4.7.0" + "version": "==4.8.0" }, "pickleshare": { "hashes": [ @@ -803,11 +789,10 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780", - "sha256:2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1", - "sha256:977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55" + "sha256:a402e9bf468b63314e37460b68ba68243d55b2f8c4d0192f85a019af3945050e", + "sha256:c93e53af97f630f12f5f62a3274e79527936ed466f038953dfa379d4941f651a" ], - "version": "==2.0.9" + "version": "==3.0.3" }, "ptyprocess": { "hashes": [ @@ -818,31 +803,31 @@ }, "pygments": { "hashes": [ - "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", - "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297" + "sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b", + "sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe" ], - "version": "==2.4.2" + "version": "==2.5.2" }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" ], - "version": "==1.12.0" + "version": "==1.14.0" }, "traitlets": { "hashes": [ - "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", - "sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9" + "sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44", + "sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7" ], - "version": "==4.3.2" + "version": "==4.3.3" }, "wcwidth": { "hashes": [ - "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", - "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603", + "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8" ], - "version": "==0.1.7" + "version": "==0.1.8" } } } diff --git a/requirements.txt b/requirements.txt index 20ba52c5b..c85559fa2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,7 +39,7 @@ pdftotext==2.1.1 pillow==5.4.1 pluggy==0.12.0 ply==3.11 -psycopg2==2.7.7 +psycopg2==2.8.4 py==1.8.0 pycodestyle==2.4.0 pygments==2.4.2 diff --git a/src/paperless/settings.py b/src/paperless/settings.py index ddc903857..ffd1140a6 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -60,7 +60,7 @@ def __get_boolean(key, default="NO"): ALLOWED_HOSTS = _allowed_hosts.split(",") FORCE_SCRIPT_NAME = os.getenv("PAPERLESS_FORCE_SCRIPT_NAME") - + # Application definition INSTALLED_APPS = [ @@ -109,7 +109,7 @@ def __get_boolean(key, default="NO"): STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' # We allow CORS from localhost:8080 -CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "localhost:8080").split(",")) +CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "http://localhost:8080,https://localhost:8080").split(",")) # If auth is disabled, we just use our "bypass" authentication middleware if bool(os.getenv("PAPERLESS_DISABLE_LOGIN", "false").lower() in ("yes", "y", "1", "t", "true")): From 19b9b2a396d2fe9a32b48bc0b2d7b61db557fc1b Mon Sep 17 00:00:00 2001 From: Johannes Wienke <languitar@semipol.de> Date: Sat, 29 Feb 2020 17:57:47 +0100 Subject: [PATCH 073/101] Upgrade Docker image to Alpine 3.11 This make tesseract 4.1 avaialbe, which fixes some things like infinite processing loops on some documents: tesseract-ocr/tesseract#2288 --- Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 30eb3a5bc..608254648 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.10 +FROM alpine:3.11 LABEL maintainer="The Paperless Project https://github.com/the-paperless-project/paperless" \ contributors="Guy Addadi <addadi@gmail.com>, Pit Kleyersburg <pitkley@googlemail.com>, \ @@ -52,6 +52,9 @@ RUN apk add --no-cache \ adduser -D -u 1000 -G paperless -h /usr/src/paperless paperless && \ chown -Rh paperless:paperless /usr/src/paperless && \ mkdir -p $PAPERLESS_EXPORT_DIR && \ +# Avoid setrlimit warnings +# See: https://gitlab.alpinelinux.org/alpine/aports/issues/11122 + echo 'Set disable_coredump false' >> /etc/sudo.conf && \ # Setup entrypoint chmod 755 /sbin/docker-entrypoint.sh @@ -67,4 +70,4 @@ COPY data/ /usr/src/paperless/data/ COPY media/ /usr/src/paperless/media/ # Collect static files -RUN sudo -HEu paperless /usr/src/paperless/src/manage.py collectstatic --clear --no-input \ No newline at end of file +RUN sudo -HEu paperless /usr/src/paperless/src/manage.py collectstatic --clear --no-input From a3aab0cb48c6bef7385ee5e2af758cc6544011e6 Mon Sep 17 00:00:00 2001 From: Johannes Wienke <languitar@semipol.de> Date: Sun, 8 Mar 2020 18:26:29 +0100 Subject: [PATCH 074/101] Remove duplicated date parsing test The exact same tests existed twice in the file. --- src/paperless_tesseract/tests/test_date.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/paperless_tesseract/tests/test_date.py b/src/paperless_tesseract/tests/test_date.py index ac2f9648f..4f931737b 100644 --- a/src/paperless_tesseract/tests/test_date.py +++ b/src/paperless_tesseract/tests/test_date.py @@ -172,13 +172,3 @@ def test_crazy_date_future(self, *args): document = RasterisedDocumentParser("/dev/null") document.get_text() self.assertIsNone(document.get_date()) - - @mock.patch( - "paperless_tesseract.parsers.RasterisedDocumentParser.get_text", - return_value="01-07-0590 00:00:00" - ) - @mock.patch(MOCK_SCRATCH, SCRATCH) - def test_crazy_date_past(self, *args): - document = RasterisedDocumentParser("/dev/null") - document.get_text() - self.assertIsNone(document.get_date()) From a311cd498c984d032e53319082871b51d42654e6 Mon Sep 17 00:00:00 2001 From: Johannes Wienke <languitar@semipol.de> Date: Sun, 8 Mar 2020 18:35:28 +0100 Subject: [PATCH 075/101] Handle dateparser ValueErrors When parsing dates from the document text or filenames, correctly handle values errors indicating broken dates. Newly added tests ensure that this handling works properly. --- src/documents/parsers.py | 4 ++-- src/paperless_tesseract/tests/test_date.py | 26 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/documents/parsers.py b/src/documents/parsers.py index 142ebba68..c0a80a55d 100644 --- a/src/documents/parsers.py +++ b/src/documents/parsers.py @@ -108,7 +108,7 @@ def __parser(ds, date_order): try: date = __parser(date_string, self.FILENAME_DATE_ORDER) - except TypeError: + except (TypeError, ValueError): # Skip all matches that do not parse to a proper date continue @@ -134,7 +134,7 @@ def __parser(ds, date_order): try: date = __parser(date_string, self.DATE_ORDER) - except TypeError: + except (TypeError, ValueError): # Skip all matches that do not parse to a proper date continue diff --git a/src/paperless_tesseract/tests/test_date.py b/src/paperless_tesseract/tests/test_date.py index 4f931737b..9e9d48b90 100644 --- a/src/paperless_tesseract/tests/test_date.py +++ b/src/paperless_tesseract/tests/test_date.py @@ -172,3 +172,29 @@ def test_crazy_date_future(self, *args): document = RasterisedDocumentParser("/dev/null") document.get_text() self.assertIsNone(document.get_date()) + + @mock.patch( + "paperless_tesseract.parsers.RasterisedDocumentParser.get_text", + return_value="20 408000l 2475" + ) + @mock.patch(MOCK_SCRATCH, SCRATCH) + def test_crazy_date_with_spaces(self, *args): + document = RasterisedDocumentParser("/dev/null") + document.get_text() + self.assertIsNone(document.get_date()) + + @mock.patch( + "paperless_tesseract.parsers.RasterisedDocumentParser.get_text", + return_value="No date in here" + ) + @mock.patch( + "paperless_tesseract.parsers.RasterisedDocumentParser." + "FILENAME_DATE_ORDER", + new_callable=mock.PropertyMock, + return_value="YMD" + ) + @mock.patch(MOCK_SCRATCH, SCRATCH) + def test_filename_date_parse_invalid(self, *args): + document = RasterisedDocumentParser("/tmp/20 408000l 2475 - test.pdf") + document.get_text() + self.assertIsNone(document.get_date()) From 7f1e1052fe5b5195894da968c2f816de65f5133b Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 28 Mar 2020 20:57:23 +0000 Subject: [PATCH 076/101] Get rid of fill_list and rather use defaultdict --- src/documents/models.py | 28 ++++++++--------------- src/documents/tests/test_file_handling.py | 2 +- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 4929ea459..39dcc4a37 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -328,25 +328,15 @@ def generate_source_filename(self): if settings.PAPERLESS_FILENAME_FORMAT is not None: tag = defaultdict(lambda: slugify(None), self.many_to_dictionary(self.tags)) - list_length = 10 - tags = self.many_to_list(self.tags) - while True: - tags = Document.fill_list(tags, list_length, None) - try: - path = settings.PAPERLESS_FILENAME_FORMAT.format( - correspondent=slugify(self.correspondent), - title=slugify(self.title), - created=slugify(self.created), - added=slugify(self.added), - tag=tag, - tags=tags) - break - except IndexError: - list_length *= 10 - - if list_length > 1000: - path = "" - break + tags = defaultdict(lambda: slugify(None), + enumerate(self.many_to_list(self.tags))) + path = settings.PAPERLESS_FILENAME_FORMAT.format( + correspondent=slugify(self.correspondent), + title=slugify(self.title), + created=slugify(self.created), + added=slugify(self.added), + tag=tag, + tags=tags) else: path = "" diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 3065948ea..f6c8d0eba 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -264,7 +264,7 @@ def test_tags_out_of_bounds_10000000(self): # Ensure that filename is properly generated tmp = document.source_filename self.assertEqual(document.generate_source_filename(), - "0000001.pdf") + "none-0000001.pdf") document.create_source_directory() Path(document.source_path).touch() From 845313db5226f02a67b8d1b954a5ef8ccf0d2815 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 28 Mar 2020 20:57:57 +0000 Subject: [PATCH 077/101] Ensure, that document root is not deleted --- src/documents/models.py | 6 +++++- src/documents/tests/test_file_handling.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 39dcc4a37..17357c1a7 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -415,7 +415,10 @@ def set_filename(self, filename): def try_delete_empty_directories(directory): # Go up in the directory hierarchy and try to delete all directories - while directory != Document.filename_to_path(""): + directory = os.path.normpath(directory) + root = os.path.normpath(Document.filename_to_path("")) + + while directory != root: # Try to delete the current directory try: os.rmdir(directory) @@ -425,6 +428,7 @@ def try_delete_empty_directories(directory): # Cut off actual directory and go one level up directory, _ = os.path.split(directory) + directory = os.path.normpath(directory) @receiver(models.signals.m2m_changed, sender=Document.tags.through) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index f6c8d0eba..fae1c0634 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -319,7 +319,7 @@ def test_nested_directory_cleanup(self): self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + "/documents/originals/none"), False) self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + - "/documents/originals"), False) + "/documents/originals"), True) @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) From 07bb9aa723275ea691abf4c13612dd6f877a08b4 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Sat, 28 Mar 2020 21:04:55 +0000 Subject: [PATCH 078/101] Allow filename to use tags[KEY] and tags[INDEX] --- paperless.conf.example | 2 +- src/documents/models.py | 20 +++++--------------- src/documents/tests/test_file_handling.py | 6 +++--- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/paperless.conf.example b/paperless.conf.example index a375ae8ba..b99995b8f 100644 --- a/paperless.conf.example +++ b/paperless.conf.example @@ -60,7 +60,7 @@ PAPERLESS_EMAIL_SECRET="" # * {title} # * {created} # * {added} -# * {tag[KEY]} If your tags conform to key_value or key-value +# * {tags[KEY]} If your tags conform to key_value or key-value # * {tags[INDEX]} If your tags are strings, select the tag by index # Uniqueness of filenames is ensured, as an incrementing counter is attached # to each filename. diff --git a/src/documents/models.py b/src/documents/models.py index 17357c1a7..006c214fa 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -289,7 +289,10 @@ def many_to_dictionary(field): # entries contain an _ or - which will be used as a delimiter mydictionary = dict() - for t in field.all(): + for index, t in enumerate(field.all()): + # Populate tag names by index + mydictionary[index] = slugify(t.name) + # Find delimiter delimiter = t.name.find('_') @@ -306,16 +309,6 @@ def many_to_dictionary(field): return mydictionary - @staticmethod - def many_to_list(field): - # Converts ManyToManyField to list - mylist = list() - - for t in field.all(): - mylist.append(slugify(t.name)) - - return mylist - @staticmethod def fill_list(input_list, length, filler): while len(input_list) < length: @@ -326,16 +319,13 @@ def fill_list(input_list, length, filler): def generate_source_filename(self): # Create filename based on configured format if settings.PAPERLESS_FILENAME_FORMAT is not None: - tag = defaultdict(lambda: slugify(None), - self.many_to_dictionary(self.tags)) tags = defaultdict(lambda: slugify(None), - enumerate(self.many_to_list(self.tags))) + self.many_to_dictionary(self.tags)) path = settings.PAPERLESS_FILENAME_FORMAT.format( correspondent=slugify(self.correspondent), title=slugify(self.title), created=slugify(self.created), added=slugify(self.added), - tag=tag, tags=tags) else: path = "" diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index fae1c0634..7af99adfc 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -145,7 +145,7 @@ def test_directory_not_empty(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_FILENAME_FORMAT="{tag[type]}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_with_underscore(self): document = Document() document.file_type = "pdf" @@ -168,7 +168,7 @@ def test_tags_with_underscore(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_FILENAME_FORMAT="{tag[type]}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_with_dash(self): document = Document() document.file_type = "pdf" @@ -191,7 +191,7 @@ def test_tags_with_dash(self): @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) - @override_settings(PAPERLESS_FILENAME_FORMAT="{tag[type]}") + @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_malformed(self): document = Document() document.file_type = "pdf" From 6318e920d5871cb869ec020721349b6737cef546 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Wed, 1 Apr 2020 19:37:21 +0000 Subject: [PATCH 079/101] Remove now unused fill_list --- src/documents/models.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 006c214fa..9e57b7e7f 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -309,13 +309,6 @@ def many_to_dictionary(field): return mydictionary - @staticmethod - def fill_list(input_list, length, filler): - while len(input_list) < length: - input_list.append(slugify(filler)) - - return input_list - def generate_source_filename(self): # Create filename based on configured format if settings.PAPERLESS_FILENAME_FORMAT is not None: From 4fc1e67e9bdb565b702783446d3922dfb9974b7c Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Fri, 10 Apr 2020 12:53:34 +0000 Subject: [PATCH 080/101] Fix: always use source_filename attribute when accessing a file --- src/documents/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/documents/models.py b/src/documents/models.py index 9e57b7e7f..b81b4d42d 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -436,7 +436,7 @@ def update_filename(sender, instance, **kwargs): instance.create_source_directory() # Determine the full "current" path - path_current = instance.filename_to_path(instance.filename) + path_current = instance.filename_to_path(instance.source_filename) # Move file try: From f64b5bf737505c68ad6498f2aa4b9066961b2af4 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Fri, 10 Apr 2020 12:54:07 +0000 Subject: [PATCH 081/101] Recover from accidentally renamed files --- src/documents/models.py | 54 +++++++++++++ src/documents/tests/test_file_handling.py | 94 +++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/src/documents/models.py b/src/documents/models.py index b81b4d42d..ba5b861c6 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -276,11 +276,43 @@ def __str__(self): return "{}: {}".format(created, self.correspondent or self.title) return str(created) + def find_renamed_document(self, subdirectory=""): + suffix = "%07i.%s" % (self.pk, self.file_type) + + # Append .gpg for encrypted files + if self.storage_type == self.STORAGE_TYPE_GPG: + suffix += ".gpg" + + # Go up in the directory hierarchy and try to delete all directories + root = os.path.normpath(Document.filename_to_path(subdirectory)) + + for filename in os.listdir(root): + if filename.endswith(suffix): + return os.path.join(subdirectory, filename) + + fullname = os.path.join(subdirectory, filename) + if os.path.isdir(Document.filename_to_path(fullname)): + return self.find_renamed_document(fullname) + + return None + @property def source_filename(self): + # Initial filename generation (for new documents) if self.filename is None: self.filename = self.generate_source_filename() + # Check if document is still available under filename + elif not os.path.isfile(Document.filename_to_path(self.filename)): + recovered_filename = self.find_renamed_document() + + # If we have found the file, save filename and clean up empty dirs + if recovered_filename is not None: + self.filename = recovered_filename + self.save() + + delete_all_empty_subdirectories(Document.filename_to_path("")) + return self.filename @staticmethod @@ -414,6 +446,28 @@ def try_delete_empty_directories(directory): directory = os.path.normpath(directory) +def delete_all_empty_subdirectories(directory): + # Go through all folders and try to delete all directories + root = os.path.normpath(Document.filename_to_path(directory)) + + for filename in os.listdir(root): + fullname = os.path.join(directory, filename) + + if not os.path.isdir(Document.filename_to_path(fullname)): + continue + + # Try to delete the directory + try: + os.rmdir(Document.filename_to_path(fullname)) + continue + except os.error: + # Directory not empty, no need to go further up + continue + + # Go into subdirectory to see, if there is more to delete + delete_all_empty_subdirectories(os.path.join(directory, filename)) + + @receiver(models.signals.m2m_changed, sender=Document.tags.through) @receiver(models.signals.post_save, sender=Document) def update_filename(sender, instance, **kwargs): diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 7af99adfc..0da2c27e7 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -331,3 +331,97 @@ def test_format_none(self): document.save() self.assertEqual(document.generate_source_filename(), "0000001.pdf") + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") + def test_document_renamed(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "none/none-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + # Test source_path + self.assertEqual(document.source_path, settings.MEDIA_ROOT + + "/documents/originals/none/none-0000001.pdf") + + # Rename the document "illegaly" + os.makedirs(settings.MEDIA_ROOT + "/documents/originals/test") + os.rename(settings.MEDIA_ROOT + "/documents/originals/" + + "none/none-0000001.pdf", + settings.MEDIA_ROOT + "/documents/originals/" + + "test/test-0000001.pdf") + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + + "originals/test/test-0000001.pdf"), True) + + # Set new correspondent and expect document to be saved properly + document.correspondent = Correspondent.objects.get_or_create( + name="foo")[0] + document.save() + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + + "originals/foo/foo-0000001.pdf"), True) + + # Check proper handling of files + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/foo"), True) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none"), False) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/test"), False) + self.assertEqual(document.generate_source_filename(), + "foo/foo-0000001.pdf") + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") + def test_document_renamed_encrypted(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_GPG + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "none/none-0000001.pdf.gpg") + document.create_source_directory() + Path(document.source_path).touch() + + # Test source_path + self.assertEqual(document.source_path, settings.MEDIA_ROOT + + "/documents/originals/none/none-0000001.pdf.gpg") + + # Rename the document "illegaly" + os.makedirs(settings.MEDIA_ROOT + "/documents/originals/test") + os.rename(settings.MEDIA_ROOT + "/documents/originals/" + + "none/none-0000001.pdf.gpg", + settings.MEDIA_ROOT + "/documents/originals/" + + "test/test-0000001.pdf.gpg") + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + + "originals/test/test-0000001.pdf.gpg"), True) + + # Set new correspondent and expect document to be saved properly + document.correspondent = Correspondent.objects.get_or_create( + name="foo")[0] + document.save() + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + + "originals/foo/foo-0000001.pdf.gpg"), True) + + # Check proper handling of files + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/foo"), True) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none"), False) + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/test"), False) + self.assertEqual(document.generate_source_filename(), + "foo/foo-0000001.pdf.gpg") From ab908fee43e6a44bd8a88d1520e592246c6d4ba2 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Fri, 10 Apr 2020 13:12:17 +0000 Subject: [PATCH 082/101] Remove temporary directories after failed tests --- src/documents/tests/test_file_handling.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 0da2c27e7..1dbe1ca18 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -4,6 +4,7 @@ from unittest import mock from uuid import uuid4 from pathlib import Path +from shutil import rmtree from dateutil import tz from django.test import TestCase, override_settings @@ -14,6 +15,19 @@ class TestDate(TestCase): + def tearDown(self): + # Delete all temporary directories from failed tests + root = os.path.normpath("/tmp") + + for filename in os.listdir(root): + fullname = os.path.join(root, filename) + + if not os.path.isdir(fullname): + continue + + if filename.startswith("paperless-tests-"): + shutil.rmtree(fullname, ignore_errors=True) + @override_settings(PAPERLESS_FILENAME_FORMAT="") def test_source_filename(self): document = Document() From db6f423ca7348e973ec8654f3a95f9c341968d4c Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 13 Apr 2020 07:12:48 +0000 Subject: [PATCH 083/101] Add: Ability to specifically remove temporary directories that have been used by a unit test --- src/documents/tests/test_file_handling.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 1dbe1ca18..50f3fe485 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -15,18 +15,14 @@ class TestDate(TestCase): - def tearDown(self): - # Delete all temporary directories from failed tests - root = os.path.normpath("/tmp") - - for filename in os.listdir(root): - fullname = os.path.join(root, filename) + deletion_list = [] - if not os.path.isdir(fullname): - continue + def add_to_deletion_list(self, dirname): + self.deletion_list.append(dirname) - if filename.startswith("paperless-tests-"): - shutil.rmtree(fullname, ignore_errors=True) + def tearDown(self): + for dirname in self.deletion_list: + shutil.rmtree(dirname, ignore_errors=True) @override_settings(PAPERLESS_FILENAME_FORMAT="") def test_source_filename(self): From 6e3e06611623037ba3a6d298a1b3022976501362 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 13 Apr 2020 07:13:28 +0000 Subject: [PATCH 084/101] Removed MEDIA_ROOT setting override for test that did not require it --- src/documents/tests/test_file_handling.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 50f3fe485..b8d2b20f0 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -331,8 +331,6 @@ def test_nested_directory_cleanup(self): self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + "/documents/originals"), True) - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT=None) def test_format_none(self): document = Document() From af3f421579cf983da7f91eb7182061a4d2ff4ac3 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 13 Apr 2020 07:13:54 +0000 Subject: [PATCH 085/101] Add: make unit test add their temporary directory to the deletion list --- src/documents/tests/test_file_handling.py | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index b8d2b20f0..75ce80905 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -54,6 +54,8 @@ def test_generate_source_filename(self): @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_file_renaming(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -100,6 +102,8 @@ def test_file_renaming(self): @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_document_delete(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -124,6 +128,8 @@ def test_document_delete(self): @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_directory_not_empty(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -157,6 +163,8 @@ def test_directory_not_empty(self): format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_with_underscore(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -180,6 +188,8 @@ def test_tags_with_underscore(self): format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_with_dash(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -203,6 +213,8 @@ def test_tags_with_dash(self): format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_malformed(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -226,6 +238,8 @@ def test_tags_malformed(self): format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[0]}") def test_tags_all(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -248,6 +262,8 @@ def test_tags_all(self): format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[0]}") def test_tags_out_of_bounds_0(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -266,6 +282,8 @@ def test_tags_out_of_bounds_0(self): format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[10000000]}") def test_tags_out_of_bounds_10000000(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -284,6 +302,8 @@ def test_tags_out_of_bounds_10000000(self): format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[99]}") def test_tags_out_of_bounds_99(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -303,6 +323,8 @@ def test_tags_out_of_bounds_99(self): @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}/{correspondent}") def test_nested_directory_cleanup(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -345,6 +367,8 @@ def test_format_none(self): @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_document_renamed(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -392,6 +416,8 @@ def test_document_renamed(self): @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_document_renamed_encrypted(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_GPG From 81c6a8abf00283eeac63e2ce145a06656504fe2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= <flameeyes@flameeyes.com> Date: Sun, 12 Apr 2020 01:21:43 +0100 Subject: [PATCH 086/101] Update unpaper link to point to the GitHub repository. While I have been "maintaining" unpaper for the past nine years, I have not spent any time on it for the past seven or so, beside kicking it down the road. I'm now trying to put it into a position where it can be taken over by someone who has interest in it. The first step is clearly to remove references to my own website where possible. --- README-de.md | 2 +- README-el.md | 2 +- README.md | 2 +- docs/requirements.rst | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README-de.md b/README-de.md index 06ffd5393..cc825ceba 100644 --- a/README-de.md +++ b/README-de.md @@ -42,7 +42,7 @@ Dies alles ist eine wirklich ziemlich einfache, glänzende und benutzerfreundlic * [ImageMagick](http://imagemagick.org/) wandelt Bilder zwischen Farbe und Graustufen um. * [Tesseract](https://github.com/tesseract-ocr) erledigt die Buchstabenerkennung. -* [Unpaper](https://www.flameeyes.eu/projects/unpaper) bereinigt und begradigt das eingescannte Bild. +* [Unpaper](https://github.com/unpaper/unpaper) bereinigt und begradigt das eingescannte Bild. * [GNU Privacy Guard](https://gnupg.org/) wird als Verschlüsselungsbackend genutzt. * [Python 3](https://python.org/) ist die Sprache des Projekts. * [Pillow](https://pypi.python.org/pypi/pillowfight/) lädt die Bilddaten als Python-Objekt, um sie mit PyOCR zu verwenden. diff --git a/README-el.md b/README-el.md index de62a7516..dfb85e76f 100644 --- a/README-el.md +++ b/README-el.md @@ -41,7 +41,7 @@ * [ImageMagick](http://imagemagick.org/) μετατρέπει τις εικόνες σε έγχρωμες και ασπρόμαυρες. * [Tesseract](https://github.com/tesseract-ocr) κάνει την αναγνώρηση των χαρακτήρων. -* [Unpaper](https://www.flameeyes.eu/projects/unpaper) despeckles and deskews the scanned image. +* [Unpaper](https://github.com/unpaper/unpaper) despeckles and deskews the scanned image. * [GNU Privacy Guard](https://gnupg.org/) χρησιμοποιείται για κρυπτογράφηση στο backend. * [Python 3](https://python.org/) είναι η γλώσσα του project. * [Pillow](https://pypi.python.org/pypi/pillowfight/) Φορτώνει την εικόνα σαν αντικείμενο στην python και μπορεί να χρησιμοποιηθεί με PyOCR diff --git a/README.md b/README.md index 002b857d0..b63a3a3ba 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ This is all really a quite simple, shiny, user-friendly wrapper around some very * [ImageMagick](http://imagemagick.org/) converts the images between colour and greyscale. * [Tesseract](https://github.com/tesseract-ocr) does the character recognition. -* [Unpaper](https://www.flameeyes.eu/projects/unpaper) despeckles and deskews the scanned image. +* [Unpaper](https://github.com/unpaper/unpaper) despeckles and deskews the scanned image. * [GNU Privacy Guard](https://gnupg.org/) is used as the encryption backend. * [Python 3](https://python.org/) is the language of the project. * [Pillow](https://pypi.python.org/pypi/pillowfight/) loads the image data as a python object to be used with PyOCR. diff --git a/docs/requirements.rst b/docs/requirements.rst index e528fdae7..54f0d9216 100644 --- a/docs/requirements.rst +++ b/docs/requirements.rst @@ -18,7 +18,7 @@ should work) that has the following software installed: .. _GNU Privacy Guard: https://gnupg.org .. _Tesseract: https://github.com/tesseract-ocr .. _Imagemagick: http://imagemagick.org/ -.. _unpaper: https://www.flameeyes.eu/projects/unpaper +.. _unpaper: https://github.com/unpaper/unpaper .. _libpoppler-cpp-dev: https://poppler.freedesktop.org/ .. _optipng: http://optipng.sourceforge.net/ From 282b2110d891fc87b637b36a920230c9cb628c39 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 13 Apr 2020 13:26:05 +0000 Subject: [PATCH 087/101] Fix: made try_delete_empty_directories and delete_all_empty_subdirectories staticmethods --- src/documents/models.py | 66 +++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index ba5b861c6..9099803cf 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -428,44 +428,46 @@ def set_filename(self, filename): self.filename = filename -def try_delete_empty_directories(directory): - # Go up in the directory hierarchy and try to delete all directories - directory = os.path.normpath(directory) - root = os.path.normpath(Document.filename_to_path("")) + @staticmethod + def try_delete_empty_directories(directory): + # Go up in the directory hierarchy and try to delete all directories + directory = os.path.normpath(directory) + root = os.path.normpath(Document.filename_to_path("")) - while directory != root: - # Try to delete the current directory - try: - os.rmdir(directory) - except os.error: - # Directory not empty, no need to go further up - return + while directory != root: + # Try to delete the current directory + try: + os.rmdir(directory) + except os.error: + # Directory not empty, no need to go further up + return - # Cut off actual directory and go one level up - directory, _ = os.path.split(directory) - directory = os.path.normpath(directory) + # Cut off actual directory and go one level up + directory, _ = os.path.split(directory) + directory = os.path.normpath(directory) -def delete_all_empty_subdirectories(directory): - # Go through all folders and try to delete all directories - root = os.path.normpath(Document.filename_to_path(directory)) + @staticmethod + def delete_all_empty_subdirectories(directory): + # Go through all folders and try to delete all directories + root = os.path.normpath(Document.filename_to_path(directory)) - for filename in os.listdir(root): - fullname = os.path.join(directory, filename) + for filename in os.listdir(root): + fullname = os.path.join(directory, filename) - if not os.path.isdir(Document.filename_to_path(fullname)): - continue + if not os.path.isdir(Document.filename_to_path(fullname)): + continue - # Try to delete the directory - try: - os.rmdir(Document.filename_to_path(fullname)) - continue - except os.error: - # Directory not empty, no need to go further up - continue + # Go into subdirectory to see, if there is more to delete + Document.delete_all_empty_subdirectories(os.path.join(directory, filename)) - # Go into subdirectory to see, if there is more to delete - delete_all_empty_subdirectories(os.path.join(directory, filename)) + # Try to delete the directory + try: + os.rmdir(Document.filename_to_path(fullname)) + continue + except os.error: + # Directory not empty, no need to go further up + continue @receiver(models.signals.m2m_changed, sender=Document.tags.through) @@ -502,7 +504,7 @@ def update_filename(sender, instance, **kwargs): # Delete empty directory old_dir = os.path.dirname(instance.filename) old_path = instance.filename_to_path(old_dir) - try_delete_empty_directories(old_path) + Document.try_delete_empty_directories(old_path) instance.filename = new_filename @@ -530,7 +532,7 @@ def delete_files(sender, instance, **kwargs): # And remove the directory (if applicable) old_dir = os.path.dirname(instance.filename) old_path = instance.filename_to_path(old_dir) - try_delete_empty_directories(old_path) + Document.try_delete_empty_directories(old_path) class Log(models.Model): From 001e40d6331167542cfe1895c62d4e53bc2ef6e7 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 13 Apr 2020 13:31:29 +0000 Subject: [PATCH 088/101] Fix: made try_delete_empty_directories and delete_all_empty_subdirectories staticmethods --- src/documents/models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 9099803cf..368d0f46c 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -311,7 +311,8 @@ def source_filename(self): self.filename = recovered_filename self.save() - delete_all_empty_subdirectories(Document.filename_to_path("")) + Document.delete_all_empty_subdirectories( + Document.filename_to_path("")) return self.filename @@ -427,7 +428,6 @@ def set_filename(self, filename): if os.path.isfile(Document.filename_to_path(filename)): self.filename = filename - @staticmethod def try_delete_empty_directories(directory): # Go up in the directory hierarchy and try to delete all directories @@ -446,7 +446,6 @@ def try_delete_empty_directories(directory): directory, _ = os.path.split(directory) directory = os.path.normpath(directory) - @staticmethod def delete_all_empty_subdirectories(directory): # Go through all folders and try to delete all directories @@ -459,7 +458,8 @@ def delete_all_empty_subdirectories(directory): continue # Go into subdirectory to see, if there is more to delete - Document.delete_all_empty_subdirectories(os.path.join(directory, filename)) + Document.delete_all_empty_subdirectories( + os.path.join(directory, filename)) # Try to delete the directory try: From d43b6a924d4cd1158957c6a9a5c040d83af46240 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 13 Apr 2020 13:32:08 +0000 Subject: [PATCH 089/101] Add: more error handling --- src/documents/models.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 368d0f46c..518a7b617 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -306,13 +306,20 @@ def source_filename(self): elif not os.path.isfile(Document.filename_to_path(self.filename)): recovered_filename = self.find_renamed_document() - # If we have found the file, save filename and clean up empty dirs + # If we have found the file so update the filename if recovered_filename is not None: + logger = logging.getLogger(__name__) + logger.warning("Filename of document " + str(self.id) + + " has changed and was successfully updated") self.filename = recovered_filename - self.save() + # Remove all empty subdirectories from MEDIA_ROOT Document.delete_all_empty_subdirectories( Document.filename_to_path("")) + else: + logger = logging.getLogger(__name__) + logger.error("File of document " + str(self.id) + " has " + + "gone and could not be recovered") return self.filename @@ -477,6 +484,10 @@ def update_filename(sender, instance, **kwargs): if instance.filename is None: return + # Check is file exists and update filename otherwise + if not os.path.isfile(Document.filename_to_path(instance.filename)): + instance.filename = instance.source_filename + # Build the new filename new_filename = instance.generate_source_filename() @@ -500,6 +511,11 @@ def update_filename(sender, instance, **kwargs): except PermissionError: # Do not update filename in object return + except FileNotFoundError: + logger = logging.getLogger(__name__) + logger.error("Renaming of document " + str(instance.id) + " failed " + + "as file " + instance.filename + " was no longer present") + return # Delete empty directory old_dir = os.path.dirname(instance.filename) From 4772480c8349f7960c33251bc068a494a6dc3d14 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Mon, 13 Apr 2020 13:30:15 +0000 Subject: [PATCH 090/101] Add: more tests --- src/documents/tests/test_file_handling.py | 155 ++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 75ce80905..b00ff68c7 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -97,6 +97,45 @@ def test_file_renaming(self): self.assertEqual(document.generate_source_filename(), "test/test-0000001.pdf.gpg") + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") + def test_file_renaming_missing_permissions(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "none/none-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + # Test source_path + self.assertEqual(document.source_path, settings.MEDIA_ROOT + + "/documents/originals/none/none-0000001.pdf") + + # Make the folder read- and execute-only (no writing and no renaming) + os.chmod(settings.MEDIA_ROOT + "/documents/originals/none", 0o555) + + # Set a correspondent and save the document + document.correspondent = Correspondent.objects.get_or_create( + name="test")[0] + document.save() + + # Check proper handling of files + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + + "originals/none/none-0000001.pdf"), True) + self.assertEqual(document.source_filename, + "none/none-0000001.pdf") + + os.chmod(settings.MEDIA_ROOT + "/documents/originals/none", 0o666) + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + @@ -123,6 +162,16 @@ def test_document_delete(self): self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + "/documents/originals/none"), False) + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") + def test_document_delete_nofile(self): + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + document.delete() + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + @@ -393,6 +442,8 @@ def test_document_renamed(self): "test/test-0000001.pdf") self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + "originals/test/test-0000001.pdf"), True) + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + + "originals/none/none-0000001.pdf"), False) # Set new correspondent and expect document to be saved properly document.correspondent = Correspondent.objects.get_or_create( @@ -442,6 +493,8 @@ def test_document_renamed_encrypted(self): "test/test-0000001.pdf.gpg") self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + "originals/test/test-0000001.pdf.gpg"), True) + self.assertEqual(os.path.isfile(settings.MEDIA_ROOT + "/documents/" + + "originals/none/none-0000001.pdf"), False) # Set new correspondent and expect document to be saved properly document.correspondent = Correspondent.objects.get_or_create( @@ -459,3 +512,105 @@ def test_document_renamed_encrypted(self): "/documents/originals/test"), False) self.assertEqual(document.generate_source_filename(), "foo/foo-0000001.pdf.gpg") + + def test_delete_all_empty_subdirectories(self): + # Create our working directory + tmp = "/tmp/paperless-tests-{}".format(str(uuid4())[:8]) + os.makedirs(tmp) + self.add_to_deletion_list(tmp) + + os.makedirs(os.path.join(tmp, "empty")) + os.makedirs(os.path.join(tmp, "empty", "subdirectory")) + + os.makedirs(os.path.join(tmp, "notempty")) + Path(os.path.join(tmp, "notempty", "file")).touch() + + Document.delete_all_empty_subdirectories(tmp) + + self.assertEqual(os.path.isdir(os.path.join(tmp, "notempty")), True) + self.assertEqual(os.path.isdir(os.path.join(tmp, "empty")), False) + self.assertEqual(os.path.isfile( + os.path.join(tmp, "notempty", "file")), True) + + def test_try_delete_empty_directories(self): + # Create our working directory + tmp = "/tmp/paperless-tests-{}".format(str(uuid4())[:8]) + os.makedirs(tmp) + self.add_to_deletion_list(tmp) + + os.makedirs(os.path.join(tmp, "notempty")) + Path(os.path.join(tmp, "notempty", "file")).touch() + os.makedirs(os.path.join(tmp, "notempty", "empty")) + + Document.try_delete_empty_directories( + os.path.join(tmp, "notempty", "empty")) + self.assertEqual(os.path.isdir(os.path.join(tmp, "notempty")), True) + self.assertEqual(os.path.isfile( + os.path.join(tmp, "notempty", "file")), True) + self.assertEqual(os.path.isdir( + os.path.join(tmp, "notempty", "empty")), False) + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") + def test_document_accidentally_deleted(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "none/none-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + # Test source_path + self.assertEqual(document.source_path, settings.MEDIA_ROOT + + "/documents/originals/none/none-0000001.pdf") + + # Delete the document "illegaly" + os.remove(settings.MEDIA_ROOT + "/documents/originals/" + + "none/none-0000001.pdf") + + # Set new correspondent and expect document to be saved properly + document.correspondent = Correspondent.objects.get_or_create( + name="foo")[0] + document.save() + + # Check proper handling of files + self.assertEqual(os.path.isdir(settings.MEDIA_ROOT + + "/documents/originals/none"), True) + self.assertEqual(document.source_filename, + "none/none-0000001.pdf") + + @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". + format(str(uuid4())[:8])) + @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + + "{correspondent}") + def test_set_filename(self): + self.add_to_deletion_list(settings.MEDIA_ROOT) + + document = Document() + document.file_type = "pdf" + document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED + document.save() + + # Ensure that filename is properly generated + tmp = document.source_filename + self.assertEqual(document.generate_source_filename(), + "none/none-0000001.pdf") + document.create_source_directory() + Path(document.source_path).touch() + + # Set existing filename + document.set_filename(tmp) + self.assertEqual(document.source_filename, "none/none-0000001.pdf") + + # Set non-existing filename + document.set_filename("doesnotexist") + self.assertEqual(document.source_filename, "none/none-0000001.pdf") From dfd6ca2b560bb179daeb254030610d39b9f3056c Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Wed, 15 Apr 2020 20:16:25 +0000 Subject: [PATCH 091/101] Fix: testcase left unaccessible directory --- src/documents/tests/test_file_handling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index b00ff68c7..f4e82bfb8 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -134,7 +134,7 @@ def test_file_renaming_missing_permissions(self): self.assertEqual(document.source_filename, "none/none-0000001.pdf") - os.chmod(settings.MEDIA_ROOT + "/documents/originals/none", 0o666) + os.chmod(settings.MEDIA_ROOT + "/documents/originals/none", 0o777) @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". format(str(uuid4())[:8])) From ea8dd2c1d9b36510317edb5159aa8794f462b2e3 Mon Sep 17 00:00:00 2001 From: Wolf-Bastian Poettner <bastian@poettner.de> Date: Wed, 15 Apr 2020 20:17:58 +0000 Subject: [PATCH 092/101] Add: ensure original directory is created and removed for each test case --- src/documents/tests/test_file_handling.py | 71 +++-------------------- 1 file changed, 7 insertions(+), 64 deletions(-) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index f4e82bfb8..d55a50cd2 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -20,6 +20,13 @@ class TestDate(TestCase): def add_to_deletion_list(self, dirname): self.deletion_list.append(dirname) + def setUp(self): + folder = "/tmp/paperless-tests-{}".format(str(uuid4())[:8]) + os.makedirs(folder + "/documents/originals") + storage_override = override_settings(MEDIA_ROOT=folder) + storage_override.enable() + self.add_to_deletion_list(folder) + def tearDown(self): for dirname in self.deletion_list: shutil.rmtree(dirname, ignore_errors=True) @@ -49,13 +56,9 @@ def test_generate_source_filename(self): self.assertEqual(document.generate_source_filename(), "0000001.pdf.gpg") - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_file_renaming(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -97,13 +100,9 @@ def test_file_renaming(self): self.assertEqual(document.generate_source_filename(), "test/test-0000001.pdf.gpg") - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_file_renaming_missing_permissions(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -136,13 +135,9 @@ def test_file_renaming_missing_permissions(self): os.chmod(settings.MEDIA_ROOT + "/documents/originals/none", 0o777) - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_document_delete(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -172,13 +167,9 @@ def test_document_delete_nofile(self): document.delete() - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_directory_not_empty(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -208,12 +199,8 @@ def test_directory_not_empty(self): "/documents/originals/none/none-0000001.pdftest") os.rmdir(settings.MEDIA_ROOT + "/documents/originals/none") - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_with_underscore(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -233,12 +220,8 @@ def test_tags_with_underscore(self): document.delete() - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_with_dash(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -258,12 +241,8 @@ def test_tags_with_dash(self): document.delete() - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[type]}") def test_tags_malformed(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -283,12 +262,8 @@ def test_tags_malformed(self): document.delete() - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[0]}") def test_tags_all(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -307,12 +282,8 @@ def test_tags_all(self): document.delete() - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[0]}") def test_tags_out_of_bounds_0(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -327,12 +298,8 @@ def test_tags_out_of_bounds_0(self): document.delete() - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[10000000]}") def test_tags_out_of_bounds_10000000(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -347,12 +314,8 @@ def test_tags_out_of_bounds_10000000(self): document.delete() - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{tags[99]}") def test_tags_out_of_bounds_99(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -367,13 +330,9 @@ def test_tags_out_of_bounds_99(self): document.delete() - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}/{correspondent}") def test_nested_directory_cleanup(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -411,13 +370,9 @@ def test_format_none(self): self.assertEqual(document.generate_source_filename(), "0000001.pdf") - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_document_renamed(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -462,13 +417,9 @@ def test_document_renamed(self): self.assertEqual(document.generate_source_filename(), "foo/foo-0000001.pdf") - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_document_renamed_encrypted(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_GPG @@ -550,13 +501,9 @@ def test_try_delete_empty_directories(self): self.assertEqual(os.path.isdir( os.path.join(tmp, "notempty", "empty")), False) - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_document_accidentally_deleted(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED @@ -588,13 +535,9 @@ def test_document_accidentally_deleted(self): self.assertEqual(document.source_filename, "none/none-0000001.pdf") - @override_settings(MEDIA_ROOT="/tmp/paperless-tests-{}". - format(str(uuid4())[:8])) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/" + "{correspondent}") def test_set_filename(self): - self.add_to_deletion_list(settings.MEDIA_ROOT) - document = Document() document.file_type = "pdf" document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED From 3084fa02bb8ee15a290ab395b54866e7d5e50f2e Mon Sep 17 00:00:00 2001 From: Adam Piontek <adam@73k.us> Date: Tue, 28 Apr 2020 13:05:30 -0400 Subject: [PATCH 093/101] bumping gunicorn version requirement to 20.0.4 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index c85559fa2..f870ae3a6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,7 +25,7 @@ faker==2.0.0 filelock==3.0.12 filemagic==1.6 fuzzywuzzy[speedup]==0.15.0 -gunicorn==19.9.0 +gunicorn==20.0.4 idna==2.8 imagesize==1.1.0 importlib-metadata==0.19 From d0bac60300e465e80675da0a917ea2af11edbc82 Mon Sep 17 00:00:00 2001 From: lawtancool <26829131+lawtancool@users.noreply.github.com> Date: Sun, 3 May 2020 20:16:55 -0700 Subject: [PATCH 094/101] Change gunicorn workers from 1 to 4 see https://docs.gunicorn.org/en/stable/design.html#how-many-workers --- scripts/gunicorn.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/gunicorn.conf b/scripts/gunicorn.conf index 8d2dcc6ad..3b2921a32 100644 --- a/scripts/gunicorn.conf +++ b/scripts/gunicorn.conf @@ -1,6 +1,6 @@ bind = '127.0.0.1:8000' backlog = 2048 -workers = 1 +workers = 4 worker_class = 'sync' worker_connections = 1000 timeout = 20 From a698964ab5781473ba205c8b019082c15be5aeed Mon Sep 17 00:00:00 2001 From: Johann Bauer <bauerj@bauerj.eu> Date: Mon, 4 May 2020 22:37:41 +0200 Subject: [PATCH 095/101] Add link to Paperless App to README --- README-de.md | 1 + README-el.md | 1 + README.md | 1 + 3 files changed, 3 insertions(+) diff --git a/README-de.md b/README-de.md index 06ffd5393..7289baace 100644 --- a/README-de.md +++ b/README-de.md @@ -62,6 +62,7 @@ Ich entwickle keine neuen Funktionen mehr für Paperless, weil es genau das tut, Paperless gibt es bereits seit einer Weile und Leute haben damit angefangen, Sachen rund um Paperless zu entwickeln. Wenn du einer dieser Menschen bist, kannst du dein Projekt zu dieser Liste hinzufügen: +* [Paperless App](https://github.com/bauerj/paperless_app): Eine Android/iOS-App für Paperless. * [Paperless Desktop](https://github.com/thomasbrueggemann/paperless-desktop): Eine Desktop-Oberfläche für deine Paperless-Installation. Läuft auf Mac, Linux und Windows. * [ansible-role-paperless](https://github.com/ovv/ansible-role-paperless): Eine einfache Möglichkeit, Paperless via Ansible laufen zu lassen. * [paperless-cli](https://github.com/stgarf/paperless-cli): Ein golang Kommandozeilenprogramm, welches mit Paperless interagiert. diff --git a/README-el.md b/README-el.md index de62a7516..2ac5ae38c 100644 --- a/README-el.md +++ b/README-el.md @@ -59,6 +59,7 @@ Το Paperless υπάρχει εδώ και κάποιο καιρό και άνθρωποι έχουν αρχίσει να φτιάχνουν πράγματα γύρω από αυτό. Αν είσαι ένας από αυτούς τους ανθρώπους, μπορούμε να βάλουμε το project σου σε αυτήν την λίστα: +* [Paperless App](https://github.com/bauerj/paperless_app): Μια εφαρμογή Android / iOS για Paperless. * [Paperless Desktop](https://github.com/thomasbrueggemann/paperless-desktop): Μια desktop εφαρμογή για εγκατάσταση του Paperless. Τρέχει σε Mac, Linux, και Windows. * [ansible-role-paperless](https://github.com/ovv/ansible-role-paperless): Ένας εύκολο τρόπος για να τρέχει το Paperless μέσω Ansible. diff --git a/README.md b/README.md index 002b857d0..169431cac 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ I am no longer doing new development on Paperless as it does exactly what I need Paperless has been around a while now, and people are starting to build stuff on top of it. If you're one of those people, we can add your project to this list: +* [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless. * [Paperless Desktop](https://github.com/thomasbrueggemann/paperless-desktop): A desktop UI for your Paperless installation. Runs on Mac, Linux, and Windows. * [ansible-role-paperless](https://github.com/ovv/ansible-role-paperless): An easy way to get Paperless running via Ansible. * [paperless-cli](https://github.com/stgarf/paperless-cli): A golang command line binary to interact with a Paperless instance. From c4848e9a22a53d1efe472287ebc90f0ad6986d44 Mon Sep 17 00:00:00 2001 From: Pyromane <git@chaos-iris.eu> Date: Tue, 5 May 2020 21:58:21 +0200 Subject: [PATCH 096/101] Update lxc-install.sh --- docs/examples/lxc/lxc-install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/examples/lxc/lxc-install.sh b/docs/examples/lxc/lxc-install.sh index 41ce375af..b53858e3a 100644 --- a/docs/examples/lxc/lxc-install.sh +++ b/docs/examples/lxc/lxc-install.sh @@ -89,9 +89,11 @@ apt-get -y install unpaper gnupg libpoppler-cpp-dev python3-pyocr tesseract-ocr # Needed for Apache apt-get -y install apache2 libapache2-mod-wsgi-py3 -if [ ! -f /etc/proftpd/proftpd.conf -o $(grep -c paperless /etc/proftpd/proftpd.conf) -eq 0 ]; then +if [ ! -f /etc/proftpd/proftpd.conf ]; then # Install ftp server and make sure all uplaoded files are owned by paperless apt-get -y install proftpd +fi +if [ $(grep -c paperless /etc/proftpd/proftpd.conf) -eq 0 ]; then cat <<EOF >> /etc/proftpd/proftpd.conf <Directory /home/ftpupload/> UserOwner paperless From 7f28a857abfffe081033f71f7688502103474107 Mon Sep 17 00:00:00 2001 From: GaryNg <garyng.zhongbo@gmail.com> Date: Sat, 9 May 2020 05:36:31 +0800 Subject: [PATCH 097/101] Fix a small typo --- docs/migrating.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migrating.rst b/docs/migrating.rst index 2c9e91897..c3e702bd5 100644 --- a/docs/migrating.rst +++ b/docs/migrating.rst @@ -92,7 +92,7 @@ files, the ``migrate`` step may not update anything. This is totally normal. Additionally, as new features are added, the ability to control those features is typically added by way of an environment variable set in ``paperless.conf``. You may want to take a look at the ``paperless.conf.example`` file to see if -there's anything new in there compared to what you've got int ``/etc``. +there's anything new in there compared to what you've got in ``/etc``. If you are :ref:`using Docker <setup-installation-docker>` the update process is similar: From 02698fab43329483dd051f72f2f0186ec54946da Mon Sep 17 00:00:00 2001 From: lawtancool <26829131+lawtancool@users.noreply.github.com> Date: Tue, 19 May 2020 09:41:08 -0700 Subject: [PATCH 098/101] change gunicorn workers to 3 Assuming a single core system, (2 x $num_cores) + 1 = 3 (see https://docs.gunicorn.org/en/stable/design.html#how-many-workers) --- scripts/gunicorn.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/gunicorn.conf b/scripts/gunicorn.conf index 3b2921a32..a2f456079 100644 --- a/scripts/gunicorn.conf +++ b/scripts/gunicorn.conf @@ -1,6 +1,6 @@ bind = '127.0.0.1:8000' backlog = 2048 -workers = 4 +workers = 3 worker_class = 'sync' worker_connections = 1000 timeout = 20 From 2a94e3a64859c153fadf2c6e0330a0e857674fce Mon Sep 17 00:00:00 2001 From: Frederick Robinson <frederick.robinson@frrad.com> Date: Tue, 2 Jun 2020 00:20:58 -0700 Subject: [PATCH 099/101] Adjust docker version requirements in doc The default config uses docker compose version 2.1 https://docs.docker.com/compose/compose-file/compose-versioning/#version-21 --- docs/setup.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/setup.rst b/docs/setup.rst index 9a371f889..59f408015 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -132,8 +132,8 @@ Docker Method .. caution:: If you want to use the included ``docker-compose.yml.example`` file, you - need to have at least Docker version **1.10.0** and docker-compose - version **1.6.0**. + need to have at least Docker version **1.12.0** and docker-compose + version **1.9.0**. See the `Docker installation guide`_ on how to install the current version of Docker for your operating system or Linux distribution of From 77a20e1bd28754a6990a0332dbe6d6a9da5db214 Mon Sep 17 00:00:00 2001 From: Frederick Robinson <frederick.robinson@frrad.com> Date: Tue, 2 Jun 2020 11:52:44 -0700 Subject: [PATCH 100/101] Fix warning in models.py --- src/documents/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/documents/models.py b/src/documents/models.py index 518a7b617..f051e3062 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -336,10 +336,10 @@ def many_to_dictionary(field): # Find delimiter delimiter = t.name.find('_') - if delimiter is -1: + if delimiter == -1: delimiter = t.name.find('-') - if delimiter is -1: + if delimiter == -1: continue key = t.name[:delimiter] From f96c3d021640a79b570ee1543e58b00eda62afdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannik=20B=C3=B6ltes=20=40SEMPERCODING?= <admin@reol.dev> Date: Sat, 6 Jun 2020 10:24:17 +0200 Subject: [PATCH 101/101] Update scanners.rst Added Brother MFC-9142CDN --- docs/scanners.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/scanners.rst b/docs/scanners.rst index 8f57a5a7a..9815637b1 100644 --- a/docs/scanners.rst +++ b/docs/scanners.rst @@ -19,15 +19,20 @@ that works right for you based on recommentations from other Paperless users. +---------+----------------+-----+-----+-----+----------------+ | Brother | `MFC-J5910DW`_ | yes | | | `bmsleight`_ | +---------+----------------+-----+-----+-----+----------------+ +| Brother | `MFC-9142CDN`_ | yes | | yes | `REOLDEV`_ | ++---------+----------------+-----+-----+-----+----------------+ | Fujitsu | `ix500`_ | yes | | yes | `eonist`_ | +---------+----------------+-----+-----+-----+----------------+ .. _ADS-1500W: https://www.brother.ca/en/p/ads1500w .. _MFC-J6930DW: https://www.brother.ca/en/p/MFCJ6930DW .. _MFC-J5910DW: https://www.brother.co.uk/printers/inkjet-printers/mfcj5910dw +.. _MFC-9142CDN: https://www.brother.co.uk/printers/laser-printers/mfc9140cdn .. _ix500: http://www.fujitsu.com/us/products/computing/peripheral/scanners/scansnap/ix500/ .. _danielquinn: https://github.com/danielquinn .. _ayounggun: https://github.com/ayounggun .. _bmsleight: https://github.com/bmsleight .. _eonist: https://github.com/eonist +.. _REOLDEV: https://github.com/REOLDEV +