Change path format syntax
This commit is contained in:
parent
a4746cbf60
commit
002404d82c
|
@ -93,8 +93,8 @@ pattern.
|
|||
|
||||
Default folder structure:
|
||||
```
|
||||
dirs_path={%Y}/{%m-%b}-{city}-{folder}
|
||||
name={%Y%m%d-%H%M%S}-%u{original_name}.%l{ext}|{%Y%m%d-%H%M%S}-%u{basename}.%l{ext}
|
||||
dirs_path=<%Y>/<%m-%b>-<city>-<folder>
|
||||
name=<%Y%m%d-%H%M%S>-<%u<original_name>|%u<basename>>.%l<ext>
|
||||
```
|
||||
|
||||
Example folder structure:
|
||||
|
@ -115,7 +115,7 @@ Example folder structure:
|
|||
│ └── 20150927_014138-_dsc8705.nef
|
||||
```
|
||||
|
||||
The folder structure use standard unix path separator (`/`). Fallback folder part can be optionally specified using a pipe (`|`) separator.
|
||||
The folder structure use standard unix path separator (`/`). Fallback folder part can be optionally specified using a pipe separator and brackets (`<.*|.*>`).
|
||||
|
||||
Valid keywords are:
|
||||
|
||||
|
|
|
@ -14,5 +14,5 @@ timeout=1
|
|||
day_begins=4
|
||||
|
||||
# Path format
|
||||
dirs_path={%Y}/{%m-%b}-{city}-{folder}
|
||||
name={%Y%m%d-%H%M%S}-(%u{original_name}|%u{name}).%l{ext}
|
||||
dirs_path=<%Y>/<%m-%b>-<city>-<folder>
|
||||
name=<%Y%m%d-%H%M%S>-<%u<original_name>|%u<name>>.%l<ext>
|
||||
|
|
|
@ -38,22 +38,22 @@ class FPath:
|
|||
def get_items(self):
|
||||
"""Return features items of Fpath class"""
|
||||
return {
|
||||
'album': '{album}',
|
||||
'stem': '{stem}',
|
||||
'camera_make': '{camera_make}',
|
||||
'camera_model': '{camera_model}',
|
||||
'city': '{city}',
|
||||
'custom': r'{".*"}',
|
||||
'country': '{country}',
|
||||
'date': r'{(%[a-zA-Z][^a-zA-Z]*){1,8}}', # search for date format string
|
||||
'ext': '{ext}',
|
||||
'folder': '{folder}',
|
||||
'folders': r'{folders(\[[0-9:]{0,3}\])?}',
|
||||
'location': '{location}',
|
||||
'name': '{name}',
|
||||
'original_name': '{original_name}',
|
||||
'state': '{state}',
|
||||
'title': '{title}',
|
||||
'album': '<album>',
|
||||
'stem': '<stem>',
|
||||
'camera_make': '<camera_make>',
|
||||
'camera_model': '<camera_model>',
|
||||
'city': '<city>',
|
||||
'custom': r'<".*">',
|
||||
'country': '<country>',
|
||||
'date': r'<(%[a-zA-Z][^a-zA-Z]*){1,8}>', # search for date format string
|
||||
'ext': '<ext>',
|
||||
'folder': '<folder>',
|
||||
'folders': r'<folders(\[[0-9:]{0,3}\])?>',
|
||||
'location': '<location>',
|
||||
'name': '<name>',
|
||||
'original_name': '<original_name>',
|
||||
'state': '<state>',
|
||||
'title': '<title>',
|
||||
}
|
||||
|
||||
def get_early_morning_photos_date(self, date, mask):
|
||||
|
@ -140,6 +140,9 @@ class FPath:
|
|||
part = stem
|
||||
for regex in utils.get_date_regex().values():
|
||||
part = re.sub(regex, '', part)
|
||||
# Delete separator
|
||||
if re.search('^[-_ .]', part):
|
||||
part = part[1:]
|
||||
elif item == 'date':
|
||||
date = metadata['date_media']
|
||||
# early morning photos can be grouped with previous day
|
||||
|
@ -194,7 +197,7 @@ class FPath:
|
|||
for item, regex in self.items.items():
|
||||
matched = re.search(regex, this_part)
|
||||
if matched:
|
||||
self.log.debug(f'item: {item}, mask: {matched.group()[1:-1]}')
|
||||
self.log.debug(f'item: {item}, mask: <matched.group()[1:-1]>')
|
||||
part = self.get_part(item, matched.group()[1:-1], metadata)
|
||||
self.log.debug(f'part: {part}')
|
||||
|
||||
|
@ -213,16 +216,16 @@ class FPath:
|
|||
this_part = self._substitute(regex, part, this_part)
|
||||
|
||||
# remove alternate parts inside bracket separated by |
|
||||
regex = r'[-_ .]?\(\|\)'
|
||||
regex = r'[-_ .]?\<\|\>'
|
||||
if re.search(regex, this_part):
|
||||
# Delete substitute part and separator if empty
|
||||
this_part = re.sub(regex, '', this_part)
|
||||
elif re.search(r'\(.*\)', this_part):
|
||||
regex = r'\(\|'
|
||||
elif re.search(r'\<.*\>', this_part):
|
||||
regex = r'\<\|'
|
||||
this_part = re.sub(regex, '', this_part)
|
||||
regex = r'\|.*\)'
|
||||
regex = r'\|.*\>'
|
||||
this_part = re.sub(regex, '', this_part)
|
||||
regex = r'\)'
|
||||
regex = r'\>'
|
||||
this_part = re.sub(regex, '', this_part)
|
||||
|
||||
# Delete separator char at the begining of the string if any:
|
||||
|
@ -238,7 +241,7 @@ class FPath:
|
|||
|
||||
def get_path(self, metadata: dict) -> list:
|
||||
"""
|
||||
path_format: {%Y-%d-%m}/%u{city}/{album}
|
||||
path_format: <%Y-%d-%m>/%u<city>/<album>
|
||||
Returns file path.
|
||||
"""
|
||||
path_format = self.path_format
|
||||
|
@ -252,9 +255,9 @@ class FPath:
|
|||
|
||||
if part != '':
|
||||
# Check if all masks are substituted
|
||||
if True in [c in part for c in '{}']:
|
||||
if True in [c in part for c in '<>']:
|
||||
self.log.error(
|
||||
f"Format path part invalid: {this_part}"
|
||||
f"Format path part invalid: {part}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ def get_config_dir(name):
|
|||
|
||||
APPLICATION_DIRECTORY = get_config_dir('ordigi')
|
||||
|
||||
DEFAULT_PATH = '{%Y-%m-%b}/{album}|{city}'
|
||||
DEFAULT_NAME = '{%Y-%m-%d_%H-%M-%S}-{name}-{title}.%l{ext}'
|
||||
DEFAULT_PATH = '<%Y-%m-%b>/<album>|<city>'
|
||||
DEFAULT_NAME = '<%Y-%m-%d_%H-%M-%S>-<name>-<title>.%l<ext>'
|
||||
DEFAULT_PATH_FORMAT = DEFAULT_PATH + '/' + DEFAULT_NAME
|
||||
DEFAULT_GEOCODER = 'Nominatim'
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@ def conf_path():
|
|||
conf = RawConfigParser()
|
||||
conf['Path'] = {
|
||||
'day_begins': '4',
|
||||
'dirs_path':'%u{%Y-%m}/{city}|{city}-{%Y}/{folders[:1]}/{folder}',
|
||||
'name':'{%Y-%m-%b-%H-%M-%S}-{basename}.%l{ext}'
|
||||
'dirs_path':'%u<%Y-%m>/<city>|<city>-<%Y>/<folders[:1]>/<folder>',
|
||||
'name':'<%Y-%m-%b-%H-%M-%S>-<basename>.%l<ext>'
|
||||
}
|
||||
conf['Geolocation'] = {
|
||||
'geocoder': 'Nominatium'
|
||||
|
|
|
@ -33,24 +33,24 @@ class TestFPath:
|
|||
# Item to search for:
|
||||
items = fpath.get_items()
|
||||
masks = [
|
||||
'{album}',
|
||||
'{basename}',
|
||||
'{camera_make}',
|
||||
'{camera_model}',
|
||||
'{city}',
|
||||
'{"custom"}',
|
||||
'{country}',
|
||||
'{ext}',
|
||||
'{folder}',
|
||||
'{folders[1:3]}',
|
||||
'{location}',
|
||||
'{name}',
|
||||
'{original_name}',
|
||||
'{state}',
|
||||
'{title}',
|
||||
'{%Y-%m-%d}',
|
||||
'{%Y-%m-%d_%H-%M-%S}',
|
||||
'{%Y-%m-%b}'
|
||||
'<album>',
|
||||
'<basename>',
|
||||
'<camera_make>',
|
||||
'<camera_model>',
|
||||
'<city>',
|
||||
'<"custom">',
|
||||
'<country>',
|
||||
'<ext>',
|
||||
'<folder>',
|
||||
'<folders[1:3]>',
|
||||
'<location>',
|
||||
'<name>',
|
||||
'<original_name>',
|
||||
'<state>',
|
||||
'<title>',
|
||||
'<%Y-%m-%d>',
|
||||
'<%Y-%m-%d_%H-%M-%S>',
|
||||
'<%Y-%m-%b>'
|
||||
]
|
||||
|
||||
for file_path in self.file_paths:
|
||||
|
@ -165,7 +165,7 @@ class TestCollection:
|
|||
|
||||
collection = Collection(tmp_path, cli_options=cli_options)
|
||||
# Try to change path format and sort files again
|
||||
path_format = 'test_exif/{city}/{%Y}-{name}.%l{ext}'
|
||||
path_format = 'test_exif/<city>/<%Y>-<name>.%l<ext>'
|
||||
summary = collection.sort_files([tmp_path], path_format, loc)
|
||||
|
||||
self.assert_sort(summary, 27)
|
||||
|
|
|
@ -32,8 +32,8 @@ class TestConfig:
|
|||
Read files from config and return variables
|
||||
"""
|
||||
# test valid config file
|
||||
assert conf['Path']['dirs_path'] == '%u{%Y-%m}/{city}|{city}-{%Y}/{folders[:1]}/{folder}'
|
||||
assert conf['Path']['name'] == '{%Y-%m-%b-%H-%M-%S}-{basename}.%l{ext}'
|
||||
assert conf['Path']['dirs_path'] == '%u<%Y-%m>/<city>|<city>-<%Y>/<folders[:1]>/<folder>'
|
||||
assert conf['Path']['name'] == '<%Y-%m-%b-%H-%M-%S>-<basename>.%l<ext>'
|
||||
assert conf['Path']['day_begins'] == '4'
|
||||
assert conf['Geolocation']['geocoder'] == 'Nominatium'
|
||||
|
||||
|
@ -56,7 +56,7 @@ class TestConfig:
|
|||
# """
|
||||
# config = Config(conf=conf)
|
||||
# path = config.get_path_definition()
|
||||
# assert path == '%u{%Y-%m}/{city}|{city}-{%Y}/{folders[:1]}/{folder}/{%Y-%m-%b-%H-%M-%S}-{basename}.%l{ext}'
|
||||
# assert path == '%u<%Y-%m>/<city>|<city>-<%Y>/<folders[:1]>/<folder>/<%Y-%m-%b-%H-%M-%S>-<basename>.%l<ext>'
|
||||
|
||||
def test_get_config_options(self, conf):
|
||||
config = Config(conf=conf)
|
||||
|
|
Loading…
Reference in New Issue