mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-31 02:27:10 -04: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