mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
Add unit tests for filename feature
This commit is contained in:
parent
a79a0ca302
commit
1ce6c6e2c5
@ -256,7 +256,7 @@ class Document(models.Model):
|
|||||||
added = models.DateTimeField(
|
added = models.DateTimeField(
|
||||||
default=timezone.now, editable=False, db_index=True)
|
default=timezone.now, editable=False, db_index=True)
|
||||||
|
|
||||||
filename = models.CharField(
|
filename = models.FilePathField(
|
||||||
max_length=256,
|
max_length=256,
|
||||||
editable=False,
|
editable=False,
|
||||||
default=None,
|
default=None,
|
||||||
@ -402,48 +402,70 @@ class Document(models.Model):
|
|||||||
self.filename = 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.m2m_changed, sender=Document.tags.through)
|
||||||
@receiver(models.signals.post_save, sender=Document)
|
@receiver(models.signals.post_save, sender=Document)
|
||||||
def update_filename(sender, instance, **kwargs):
|
def update_filename(sender, instance, **kwargs):
|
||||||
if instance.filename is None:
|
if instance.filename is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Build the new filename
|
# Build the new filename
|
||||||
new_filename = instance.source_filename_new()
|
new_filename = instance.source_filename_new()
|
||||||
|
|
||||||
# If the filename is the same, then nothing needs to be done
|
# If the filename is the same, then nothing needs to be done
|
||||||
if instance.filename is None or \
|
if instance.filename is None or \
|
||||||
instance.filename == new_filename:
|
instance.filename == new_filename:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if filename needs changing
|
# Check if filename needs changing
|
||||||
if new_filename != instance.filename:
|
if new_filename != instance.filename:
|
||||||
# Determine the full "target" path
|
# Determine the full "target" path
|
||||||
path_new = instance.filename_to_path(new_filename)
|
path_new = instance.filename_to_path(new_filename)
|
||||||
dir_new = instance.filename_to_path(os.path.dirname(new_filename))
|
dir_new = instance.filename_to_path(os.path.dirname(new_filename))
|
||||||
|
|
||||||
# Determine the full "current" path
|
# Determine the full "current" path
|
||||||
path_current = instance.filename_to_path(instance.filename)
|
path_current = instance.filename_to_path(instance.filename)
|
||||||
|
|
||||||
# Move file
|
# Move file
|
||||||
|
try:
|
||||||
os.rename(path_current, path_new)
|
os.rename(path_current, path_new)
|
||||||
|
except PermissionError:
|
||||||
|
# Do not update filename in object
|
||||||
|
return
|
||||||
|
|
||||||
# Delete empty directory
|
# Delete empty directory
|
||||||
old_dir = os.path.dirname(instance.filename)
|
old_dir = os.path.dirname(instance.filename)
|
||||||
old_path = instance.filename_to_path(old_dir)
|
old_path = instance.filename_to_path(old_dir)
|
||||||
if len(os.listdir(old_path)) == 0:
|
delete_empty_directory(old_path)
|
||||||
try:
|
|
||||||
os.rmdir(old_path)
|
|
||||||
except os.error:
|
|
||||||
# Directory not empty
|
|
||||||
pass
|
|
||||||
|
|
||||||
instance.filename = new_filename
|
instance.filename = new_filename
|
||||||
|
|
||||||
# Save instance
|
# Save instance
|
||||||
# This will not cause a cascade of post_save signals, as next time
|
# This will not cause a cascade of post_save signals, as next time
|
||||||
# nothing needs to be renamed
|
# nothing needs to be renamed
|
||||||
instance.save()
|
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)
|
||||||
|
|
||||||
|
# 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):
|
class Log(models.Model):
|
||||||
|
154
src/documents/tests/test_file_handling.py
Normal file
154
src/documents/tests/test_file_handling.py
Normal file
@ -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")
|
Loading…
x
Reference in New Issue
Block a user