mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Modifications for support for dates
This commit is contained in:
		| @@ -19,12 +19,11 @@ from PIL import Image | |||||||
|  |  | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.utils import timezone | from django.utils import timezone | ||||||
| from django.template.defaultfilters import slugify |  | ||||||
| from pyocr.tesseract import TesseractError | from pyocr.tesseract import TesseractError | ||||||
|  |  | ||||||
| from paperless.db import GnuPG | from paperless.db import GnuPG | ||||||
|  |  | ||||||
| from .models import Correspondent, Tag, Document, Log, FileInfo | from .models import Tag, Document, Log, FileInfo | ||||||
| from .languages import ISO639 | from .languages import ISO639 | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -92,7 +91,7 @@ class Consumer(object): | |||||||
|             if not os.path.isfile(doc): |             if not os.path.isfile(doc): | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             if not re.match(FileInfo.REGEX_TITLE, doc): |             if not re.match(FileInfo.REGEXES["title"], doc): | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             if doc in self._ignore: |             if doc in self._ignore: | ||||||
| @@ -269,7 +268,7 @@ class Consumer(object): | |||||||
|             correspondent=file_info.correspondent, |             correspondent=file_info.correspondent, | ||||||
|             title=file_info.title, |             title=file_info.title, | ||||||
|             content=text, |             content=text, | ||||||
|             file_type=file_info.suffix, |             file_type=file_info.extension, | ||||||
|             created=timezone.make_aware( |             created=timezone.make_aware( | ||||||
|                 datetime.datetime.fromtimestamp(stats.st_mtime)), |                 datetime.datetime.fromtimestamp(stats.st_mtime)), | ||||||
|             modified=timezone.make_aware( |             modified=timezone.make_aware( | ||||||
|   | |||||||
| @@ -96,11 +96,16 @@ class Command(Renderable, BaseCommand): | |||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def _get_legacy_file_name(doc): |     def _get_legacy_file_name(doc): | ||||||
|         if doc.correspondent and doc.title: |  | ||||||
|             tags = ",".join([t.slug for t in doc.tags.all()]) |         if not doc.correspondent and not doc.title: | ||||||
|             if tags: |  | ||||||
|                 return "{} - {} - {}.{}".format( |  | ||||||
|                     doc.correspondent, doc.title, tags, doc.file_type) |  | ||||||
|             return "{} - {}.{}".format( |  | ||||||
|                 doc.correspondent, doc.title, doc.file_type) |  | ||||||
|             return os.path.basename(doc.source_path) |             return os.path.basename(doc.source_path) | ||||||
|  |  | ||||||
|  |         created = doc.created.strftime("%Y%m%d%H%M%SZ") | ||||||
|  |         tags = ",".join([t.slug for t in doc.tags.all()]) | ||||||
|  |  | ||||||
|  |         if tags: | ||||||
|  |             return "{} - {} - {} - {}.{}".format( | ||||||
|  |                 created, doc.correspondent, doc.title, tags, doc.file_type) | ||||||
|  |  | ||||||
|  |         return "{} - {} - {}.{}".format( | ||||||
|  |             created, doc.correspondent, doc.title, doc.file_type) | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
|  | import dateutil.parser | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import re | import re | ||||||
| import uuid | import uuid | ||||||
|  |  | ||||||
|  | from collections import OrderedDict | ||||||
|  |  | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.core.urlresolvers import reverse | from django.core.urlresolvers import reverse | ||||||
| from django.db import models | from django.db import models | ||||||
| @@ -12,97 +15,6 @@ from django.utils import timezone | |||||||
| from .managers import LogManager | from .managers import LogManager | ||||||
|  |  | ||||||
|  |  | ||||||
| class FileInfo(object): |  | ||||||
|     def __init__(self, title, suffix, |  | ||||||
|                  correspondent=None, tags=None): |  | ||||||
|         self._title = title |  | ||||||
|         self._suffix = suffix |  | ||||||
|         self._correspondent = correspondent |  | ||||||
|         self._tags = tags |  | ||||||
|  |  | ||||||
|     REGEX_TITLE = re.compile( |  | ||||||
|         r"^.*/(.*)\.(pdf|jpe?g|png|gif|tiff)$", |  | ||||||
|         flags=re.IGNORECASE |  | ||||||
|     ) |  | ||||||
|     REGEX_CORRESPONDENT_TITLE = re.compile( |  | ||||||
|         r"^.*/(.+) - (.*)\.(pdf|jpe?g|png|gif|tiff)$", |  | ||||||
|         flags=re.IGNORECASE |  | ||||||
|     ) |  | ||||||
|     REGEX_CORRESPONDENT_TITLE_TAGS = re.compile( |  | ||||||
|         r"^.*/(.*) - (.*) - ([a-z0-9\-,]*)\.(pdf|jpe?g|png|gif|tiff)$", |  | ||||||
|         flags=re.IGNORECASE |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
|     @classmethod |  | ||||||
|     def from_path(cls, path): |  | ||||||
|         """ |  | ||||||
|         We use a crude naming convention to make handling the correspondent, |  | ||||||
|         title, and tags easier: |  | ||||||
|           "<correspondent> - <title> - <tags>.<suffix>" |  | ||||||
|           "<correspondent> - <title>.<suffix>" |  | ||||||
|           "<title>.<suffix>" |  | ||||||
|         """ |  | ||||||
|  |  | ||||||
|         def get_correspondent(correspondent_name): |  | ||||||
|             return Correspondent.objects.get_or_create( |  | ||||||
|                 name=correspondent_name, |  | ||||||
|                 defaults={"slug": slugify(correspondent_name)} |  | ||||||
|             )[0] |  | ||||||
|  |  | ||||||
|         def get_tags(tags): |  | ||||||
|             r = [] |  | ||||||
|             for t in tags.split(","): |  | ||||||
|                 r.append( |  | ||||||
|                     Tag.objects.get_or_create(slug=t, defaults={"name": t})[0]) |  | ||||||
|             return tuple(r) |  | ||||||
|  |  | ||||||
|         def get_suffix(suffix): |  | ||||||
|             suffix = suffix.lower() |  | ||||||
|             if suffix == "jpeg": |  | ||||||
|                 return "jpg" |  | ||||||
|             return suffix |  | ||||||
|  |  | ||||||
|         # First attempt: "<correspondent> - <title> - <tags>.<suffix>" |  | ||||||
|         m = re.match(cls.REGEX_CORRESPONDENT_TITLE_TAGS, path) |  | ||||||
|         if m: |  | ||||||
|             return cls( |  | ||||||
|                 title=m.group(2), |  | ||||||
|                 correspondent=get_correspondent(m.group(1)), |  | ||||||
|                 tags=get_tags(m.group(3)), |  | ||||||
|                 suffix=get_suffix(m.group(4)) |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|         # Second attempt: "<correspondent> - <title>.<suffix>" |  | ||||||
|         m = re.match(cls.REGEX_CORRESPONDENT_TITLE, path) |  | ||||||
|         if m: |  | ||||||
|             return cls( |  | ||||||
|                 title=m.group(2), |  | ||||||
|                 correspondent=get_correspondent(m.group(1)), |  | ||||||
|                 tags=(), |  | ||||||
|                 suffix=get_suffix(m.group(3)) |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|         # That didn't work, so we assume correspondent and tags are None |  | ||||||
|         m = re.match(cls.REGEX_TITLE, path) |  | ||||||
|         return FileInfo( |  | ||||||
|             title=m.group(1), tags=(), suffix=get_suffix(m.group(2))) |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def title(self): |  | ||||||
|         return self._title |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def correspondent(self): |  | ||||||
|         return self._correspondent |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def tags(self): |  | ||||||
|         return self._tags |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def suffix(self): |  | ||||||
|         return self._suffix |  | ||||||
|  |  | ||||||
| class SluggedModel(models.Model): | class SluggedModel(models.Model): | ||||||
|  |  | ||||||
|     name = models.CharField(max_length=128, unique=True) |     name = models.CharField(max_length=128, unique=True) | ||||||
| @@ -341,3 +253,136 @@ class Log(models.Model): | |||||||
|             self.group = uuid.uuid4() |             self.group = uuid.uuid4() | ||||||
|  |  | ||||||
|         models.Model.save(self, *args, **kwargs) |         models.Model.save(self, *args, **kwargs) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class FileInfo(object): | ||||||
|  |  | ||||||
|  |     # This epic regex *almost* worked for our needs, so I'm keeping it here for | ||||||
|  |     # posterity, in the hopes that we might find a way to make it work one day. | ||||||
|  |     ALMOST_REGEX = re.compile( | ||||||
|  |         r"^((?P<date>\d\d\d\d\d\d\d\d\d\d\d\d\d\dZ){separator})?" | ||||||
|  |         r"((?P<correspondent>{non_separated_word}+){separator})??" | ||||||
|  |         r"(?P<title>{non_separated_word}+)" | ||||||
|  |         r"({separator}(?P<tags>[a-z,0-9-]+))?" | ||||||
|  |         r"\.(?P<extension>[a-zA-Z.-]+)$".format( | ||||||
|  |             separator=r"\s+-\s+", | ||||||
|  |             non_separated_word=r"([\w,. ]|([^\s]-))" | ||||||
|  |         ) | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     REGEXES = OrderedDict([ | ||||||
|  |         ("created-correspondent-title-tags", re.compile( | ||||||
|  |             r"^(?P<created>\d\d\d\d\d\d\d\d(\d\d\d\d\d\d)?Z) - " | ||||||
|  |             r"(?P<correspondent>.*) - " | ||||||
|  |             r"(?P<title>.*) - " | ||||||
|  |             r"(?P<tags>[a-z0-9\-,]*)" | ||||||
|  |             r"\.(?P<extension>pdf|jpe?g|png|gif|tiff)$", | ||||||
|  |             flags=re.IGNORECASE | ||||||
|  |         )), | ||||||
|  |         ("created-title-tags", re.compile( | ||||||
|  |             r"^(?P<created>\d\d\d\d\d\d\d\d(\d\d\d\d\d\d)?Z) - " | ||||||
|  |             r"(?P<title>.*) - " | ||||||
|  |             r"(?P<tags>[a-z0-9\-,]*)" | ||||||
|  |             r"\.(?P<extension>pdf|jpe?g|png|gif|tiff)$", | ||||||
|  |             flags=re.IGNORECASE | ||||||
|  |         )), | ||||||
|  |         ("created-correspondent-title", re.compile( | ||||||
|  |             r"^(?P<created>\d\d\d\d\d\d\d\d(\d\d\d\d\d\d)?Z) - " | ||||||
|  |             r"(?P<correspondent>.*) - " | ||||||
|  |             r"(?P<title>.*)" | ||||||
|  |             r"\.(?P<extension>pdf|jpe?g|png|gif|tiff)$", | ||||||
|  |             flags=re.IGNORECASE | ||||||
|  |         )), | ||||||
|  |         ("created-title", re.compile( | ||||||
|  |             r"^(?P<created>\d\d\d\d\d\d\d\d(\d\d\d\d\d\d)?Z) - " | ||||||
|  |             r"(?P<title>.*)" | ||||||
|  |             r"\.(?P<extension>pdf|jpe?g|png|gif|tiff)$", | ||||||
|  |             flags=re.IGNORECASE | ||||||
|  |         )), | ||||||
|  |         ("correspondent-title-tags", re.compile( | ||||||
|  |             r"(?P<correspondent>.*) - " | ||||||
|  |             r"(?P<title>.*) - " | ||||||
|  |             r"(?P<tags>[a-z0-9\-,]*)" | ||||||
|  |             r"\.(?P<extension>pdf|jpe?g|png|gif|tiff)$", | ||||||
|  |             flags=re.IGNORECASE | ||||||
|  |         )), | ||||||
|  |         ("correspondent-title", re.compile( | ||||||
|  |             r"(?P<correspondent>.*) - " | ||||||
|  |             r"(?P<title>.*)?" | ||||||
|  |             r"\.(?P<extension>pdf|jpe?g|png|gif|tiff)$", | ||||||
|  |             flags=re.IGNORECASE | ||||||
|  |         )), | ||||||
|  |         ("title", re.compile( | ||||||
|  |             r"(?P<title>.*)" | ||||||
|  |             r"\.(?P<extension>pdf|jpe?g|png|gif|tiff)$", | ||||||
|  |             flags=re.IGNORECASE | ||||||
|  |         )) | ||||||
|  |     ]) | ||||||
|  |  | ||||||
|  |     def __init__(self, created=None, correspondent=None, title=None, tags=(), | ||||||
|  |                  extension=None): | ||||||
|  |  | ||||||
|  |         self.created = created | ||||||
|  |         self.title = title | ||||||
|  |         self.extension = extension | ||||||
|  |         self.correspondent = correspondent | ||||||
|  |         self.tags = tags | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def _get_created(cls, created): | ||||||
|  |         return dateutil.parser.parse("{:0<14}Z".format(created[:-1])) | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def _get_correspondent(cls, name): | ||||||
|  |         if not name: | ||||||
|  |             return None | ||||||
|  |         return Correspondent.objects.get_or_create(name=name, defaults={ | ||||||
|  |             "slug": slugify(name) | ||||||
|  |         })[0] | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def _get_title(cls, title): | ||||||
|  |         return title | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def _get_tags(cls, tags): | ||||||
|  |         r = [] | ||||||
|  |         for t in tags.split(","): | ||||||
|  |             r.append( | ||||||
|  |                 Tag.objects.get_or_create(slug=t, defaults={"name": t})[0]) | ||||||
|  |         return tuple(r) | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def _get_extension(cls, extension): | ||||||
|  |         r = extension.lower() | ||||||
|  |         if r == "jpeg": | ||||||
|  |             return "jpg" | ||||||
|  |         return r | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def _mangle_property(cls, properties, name): | ||||||
|  |         if name in properties: | ||||||
|  |             properties[name] = getattr(cls, "_get_{}".format(name))( | ||||||
|  |                 properties[name] | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def from_path(cls, path): | ||||||
|  |         """ | ||||||
|  |         We use a crude naming convention to make handling the correspondent, | ||||||
|  |         title, and tags easier: | ||||||
|  |           "<correspondent> - <title> - <tags>.<suffix>" | ||||||
|  |           "<correspondent> - <title>.<suffix>" | ||||||
|  |           "<title>.<suffix>" | ||||||
|  |         """ | ||||||
|  |  | ||||||
|  |         for regex in cls.REGEXES.values(): | ||||||
|  |             m = regex.match(os.path.basename(path)) | ||||||
|  |             if m: | ||||||
|  |                 properties = m.groupdict() | ||||||
|  |                 cls._mangle_property(properties, "created") | ||||||
|  |                 cls._mangle_property(properties, "correspondent") | ||||||
|  |                 cls._mangle_property(properties, "title") | ||||||
|  |                 cls._mangle_property(properties, "tags") | ||||||
|  |                 cls._mangle_property(properties, "extension") | ||||||
|  |                 return cls(**properties) | ||||||
|   | |||||||
| @@ -1,28 +1,36 @@ | |||||||
| from django.test import TestCase | from django.test import TestCase | ||||||
|  |  | ||||||
| from ..models import FileInfo | from ..models import Document, FileInfo | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestAttachment(TestCase): | class TestAttachment(TestCase): | ||||||
|  |  | ||||||
|     TAGS = ("tag1", "tag2", "tag3") |     TAGS = ("tag1", "tag2", "tag3") | ||||||
|     SUFFIXES = ( |     EXTENSIONS = ( | ||||||
|         "pdf", "png", "jpg", "jpeg", "gif", |         "pdf", "png", "jpg", "jpeg", "gif", | ||||||
|         "PDF", "PNG", "JPG", "JPEG", "GIF", |         "PDF", "PNG", "JPG", "JPEG", "GIF", | ||||||
|         "PdF", "PnG", "JpG", "JPeG", "GiF", |         "PdF", "PnG", "JpG", "JPeG", "GiF", | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     def _test_guess_attributes_from_name(self, path, sender, title, tags): |     def _test_guess_attributes_from_name(self, path, sender, title, tags): | ||||||
|         for suffix in self.SUFFIXES: |  | ||||||
|             f = path.format(suffix) |         for extension in self.EXTENSIONS: | ||||||
|  |  | ||||||
|  |             f = path.format(extension) | ||||||
|             file_info = FileInfo.from_path(f) |             file_info = FileInfo.from_path(f) | ||||||
|  |  | ||||||
|  |             if sender: | ||||||
|                 self.assertEqual(file_info.correspondent.name, sender, f) |                 self.assertEqual(file_info.correspondent.name, sender, f) | ||||||
|             self.assertEqual(file_info.title, title, f) |  | ||||||
|             self.assertEqual(tuple([t.slug for t in file_info.tags]), tags, f) |  | ||||||
|             if suffix.lower() == "jpeg": |  | ||||||
|                 self.assertEqual(file_info.suffix, "jpg", f) |  | ||||||
|             else: |             else: | ||||||
|                 self.assertEqual(file_info.suffix, suffix.lower(), f) |                 self.assertIsNone(file_info.correspondent, f) | ||||||
|  |  | ||||||
|  |             self.assertEqual(file_info.title, title, f) | ||||||
|  |  | ||||||
|  |             self.assertEqual(tuple([t.slug for t in file_info.tags]), tags, f) | ||||||
|  |             if extension.lower() == "jpeg": | ||||||
|  |                 self.assertEqual(file_info.extension, "jpg", f) | ||||||
|  |             else: | ||||||
|  |                 self.assertEqual(file_info.extension, extension.lower(), f) | ||||||
|  |  | ||||||
|     def test_guess_attributes_from_name0(self): |     def test_guess_attributes_from_name0(self): | ||||||
|         self._test_guess_attributes_from_name( |         self._test_guess_attributes_from_name( | ||||||
| @@ -96,7 +104,7 @@ class TestAttachment(TestCase): | |||||||
|         self._test_guess_attributes_from_name( |         self._test_guess_attributes_from_name( | ||||||
|             '/path/to/ - weird empty correspondent but should not break.{}', |             '/path/to/ - weird empty correspondent but should not break.{}', | ||||||
|             None, |             None, | ||||||
|             ' - weird empty correspondent but should not break', |             'weird empty correspondent but should not break', | ||||||
|             () |             () | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @@ -126,60 +134,171 @@ class TestAttachment(TestCase): | |||||||
|  |  | ||||||
|  |  | ||||||
| class Permutations(TestCase): | class Permutations(TestCase): | ||||||
|     valid_correspondents = ['timmy', 'Dr. McWheelie', |  | ||||||
|                             'Dash Gor-don', 'ο Θερμαστής'] |  | ||||||
|     valid_titles = ['title', 'Title w Spaces', 'Title a-dash', 'Τίτλος', ''] |  | ||||||
|     valid_tags = ['tag', 'tig,tag', '-', '0,1,2', ''] |  | ||||||
|     valid_suffixes = ['pdf', 'png', 'jpg', 'jpeg', 'gif'] |  | ||||||
|  |  | ||||||
|     def _test_guessed_attributes( |     valid_dates = ( | ||||||
|             self, filename, title, suffix, correspondent=None, tags=None): |         "20150102030405Z", | ||||||
|         file_info = FileInfo.from_path(filename) |         "20150102Z", | ||||||
|  |     ) | ||||||
|  |     valid_correspondents = [ | ||||||
|  |         "timmy", | ||||||
|  |         "Dr. McWheelie", | ||||||
|  |         "Dash Gor-don", | ||||||
|  |         "ο Θερμαστής", | ||||||
|  |         "" | ||||||
|  |     ] | ||||||
|  |     valid_titles = ["title", "Title w Spaces", "Title a-dash", "Τίτλος", ""] | ||||||
|  |     valid_tags = ["tag", "tig,tag", "tag1,tag2,tag-3"] | ||||||
|  |     valid_extensions = ["pdf", "png", "jpg", "jpeg", "gif"] | ||||||
|  |  | ||||||
|         # Required |     def _test_guessed_attributes(self, filename, created=None, | ||||||
|         self.assertEqual(file_info.title, title, filename) |                                  correspondent=None, title=None, | ||||||
|         if suffix == 'jpeg': |                                  extension=None, tags=None): | ||||||
|             suffix = 'jpg' |  | ||||||
|         self.assertEqual(file_info.suffix, suffix, filename) |         # print(filename) | ||||||
|         # Optional |         info = FileInfo.from_path(filename) | ||||||
|         if correspondent is None: |  | ||||||
|             self.assertEqual(file_info.correspondent, |         # Created | ||||||
|                              correspondent, filename) |         if created is None: | ||||||
|  |             self.assertIsNone(info.created, filename) | ||||||
|         else: |         else: | ||||||
|             self.assertEqual(file_info.correspondent.name, |             self.assertEqual(info.created.year, int(created[:4]), filename) | ||||||
|                              correspondent, filename) |             self.assertEqual(info.created.month, int(created[4:6]), filename) | ||||||
|  |             self.assertEqual(info.created.day, int(created[6:8]), filename) | ||||||
|  |  | ||||||
|  |         # Correspondent | ||||||
|  |         if correspondent: | ||||||
|  |             self.assertEqual(info.correspondent.name, correspondent, filename) | ||||||
|  |         else: | ||||||
|  |             self.assertEqual(info.correspondent, None, filename) | ||||||
|  |  | ||||||
|  |         # Title | ||||||
|  |         self.assertEqual(info.title, title, filename) | ||||||
|  |  | ||||||
|  |         # Tags | ||||||
|         if tags is None: |         if tags is None: | ||||||
|             self.assertEqual(file_info.tags, (), filename) |             self.assertEqual(info.tags, (), filename) | ||||||
|         else: |         else: | ||||||
|             self.assertEqual([t.slug for t in file_info.tags], |             self.assertEqual( | ||||||
|                              tags.split(','), |                 [t.slug for t in info.tags], tags.split(','), | ||||||
|                              filename) |                 filename | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         # Extension | ||||||
|  |         if extension == 'jpeg': | ||||||
|  |             extension = 'jpg' | ||||||
|  |         self.assertEqual(info.extension, extension, filename) | ||||||
|  |  | ||||||
|     def test_just_title(self): |     def test_just_title(self): | ||||||
|         template = '/path/to/{title}.{suffix}' |         template = '/path/to/{title}.{extension}' | ||||||
|         for title in self.valid_titles: |         for title in self.valid_titles: | ||||||
|             for suffix in self.valid_suffixes: |             for extension in self.valid_extensions: | ||||||
|                 spec = dict(title=title, suffix=suffix) |                 spec = dict(title=title, extension=extension) | ||||||
|                 filename = template.format(**spec) |                 filename = template.format(**spec) | ||||||
|                 self._test_guessed_attributes(filename, **spec) |                 self._test_guessed_attributes(filename, **spec) | ||||||
|  |  | ||||||
|     def test_title_and_correspondent(self): |     def test_title_and_correspondent(self): | ||||||
|         template = '/path/to/{correspondent} - {title}.{suffix}' |         template = '/path/to/{correspondent} - {title}.{extension}' | ||||||
|         for correspondent in self.valid_correspondents: |         for correspondent in self.valid_correspondents: | ||||||
|             for title in self.valid_titles: |             for title in self.valid_titles: | ||||||
|                 for suffix in self.valid_suffixes: |                 for extension in self.valid_extensions: | ||||||
|                     spec = dict(correspondent=correspondent, title=title, |                     spec = dict(correspondent=correspondent, title=title, | ||||||
|                                 suffix=suffix) |                                 extension=extension) | ||||||
|                     filename = template.format(**spec) |                     filename = template.format(**spec) | ||||||
|                     self._test_guessed_attributes(filename, **spec) |                     self._test_guessed_attributes(filename, **spec) | ||||||
|  |  | ||||||
|     def test_title_and_correspondent_and_tags(self): |     def test_title_and_correspondent_and_tags(self): | ||||||
|         template = '/path/to/{correspondent} - {title} - {tags}.{suffix}' |         template = '/path/to/{correspondent} - {title} - {tags}.{extension}' | ||||||
|         for correspondent in self.valid_correspondents: |         for correspondent in self.valid_correspondents: | ||||||
|             for title in self.valid_titles: |             for title in self.valid_titles: | ||||||
|                 for tags in self.valid_tags: |                 for tags in self.valid_tags: | ||||||
|                     for suffix in self.valid_suffixes: |                     for extension in self.valid_extensions: | ||||||
|                         spec = dict(correspondent=correspondent, title=title, |                         spec = dict(correspondent=correspondent, title=title, | ||||||
|                                     tags=tags, suffix=suffix) |                                     tags=tags, extension=extension) | ||||||
|                         filename = template.format(**spec) |                         filename = template.format(**spec) | ||||||
|                         self._test_guessed_attributes(filename, **spec) |                         self._test_guessed_attributes(filename, **spec) | ||||||
|  |  | ||||||
|  |     def test_created_and_correspondent_and_title_and_tags(self): | ||||||
|  |  | ||||||
|  |         template = ("/path/to/{created} - " | ||||||
|  |                     "{correspondent} - " | ||||||
|  |                     "{title} - " | ||||||
|  |                     "{tags}" | ||||||
|  |                     ".{extension}") | ||||||
|  |  | ||||||
|  |         for created in self.valid_dates: | ||||||
|  |             for correspondent in self.valid_correspondents: | ||||||
|  |                 for title in self.valid_titles: | ||||||
|  |                     for tags in self.valid_tags: | ||||||
|  |                         for extension in self.valid_extensions: | ||||||
|  |                             spec = { | ||||||
|  |                                 "created": created, | ||||||
|  |                                 "correspondent": correspondent, | ||||||
|  |                                 "title": title, | ||||||
|  |                                 "tags": tags, | ||||||
|  |                                 "extension": extension | ||||||
|  |                             } | ||||||
|  |                             self._test_guessed_attributes( | ||||||
|  |                                 template.format(**spec), **spec) | ||||||
|  |  | ||||||
|  |     def test_created_and_correspondent_and_title(self): | ||||||
|  |  | ||||||
|  |         template = ("/path/to/{created} - " | ||||||
|  |                     "{correspondent} - " | ||||||
|  |                     "{title}" | ||||||
|  |                     ".{extension}") | ||||||
|  |  | ||||||
|  |         for created in self.valid_dates: | ||||||
|  |             for correspondent in self.valid_correspondents: | ||||||
|  |                 for title in self.valid_titles: | ||||||
|  |  | ||||||
|  |                     # Skip cases where title looks like a tag as we can't | ||||||
|  |                     # accommodate such cases. | ||||||
|  |                     if title.lower() == title: | ||||||
|  |                         continue | ||||||
|  |  | ||||||
|  |                     for extension in self.valid_extensions: | ||||||
|  |                         spec = { | ||||||
|  |                             "created": created, | ||||||
|  |                             "correspondent": correspondent, | ||||||
|  |                             "title": title, | ||||||
|  |                             "extension": extension | ||||||
|  |                         } | ||||||
|  |                         self._test_guessed_attributes( | ||||||
|  |                             template.format(**spec), **spec) | ||||||
|  |  | ||||||
|  |     def test_created_and_title(self): | ||||||
|  |  | ||||||
|  |         template = ("/path/to/{created} - " | ||||||
|  |                     "{title}" | ||||||
|  |                     ".{extension}") | ||||||
|  |  | ||||||
|  |         for created in self.valid_dates: | ||||||
|  |             for title in self.valid_titles: | ||||||
|  |                 for extension in self.valid_extensions: | ||||||
|  |                     spec = { | ||||||
|  |                         "created": created, | ||||||
|  |                         "title": title, | ||||||
|  |                         "extension": extension | ||||||
|  |                     } | ||||||
|  |                     self._test_guessed_attributes( | ||||||
|  |                         template.format(**spec), **spec) | ||||||
|  |  | ||||||
|  |     def test_created_and_title_and_tags(self): | ||||||
|  |  | ||||||
|  |         template = ("/path/to/{created} - " | ||||||
|  |                     "{title} - " | ||||||
|  |                     "{tags}" | ||||||
|  |                     ".{extension}") | ||||||
|  |  | ||||||
|  |         for created in self.valid_dates: | ||||||
|  |             for title in self.valid_titles: | ||||||
|  |                 for tags in self.valid_tags: | ||||||
|  |                     for extension in self.valid_extensions: | ||||||
|  |                         spec = { | ||||||
|  |                             "created": created, | ||||||
|  |                             "title": title, | ||||||
|  |                             "tags": tags, | ||||||
|  |                             "extension": extension | ||||||
|  |                         } | ||||||
|  |                         self._test_guessed_attributes( | ||||||
|  |                             template.format(**spec), **spec) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Daniel Quinn
					Daniel Quinn