Code improvements

This commit is contained in:
Cédric Leporcq 2021-12-05 13:39:02 +01:00
parent 7688d0e7c4
commit da4a388697
6 changed files with 80 additions and 76 deletions

View File

@ -1,8 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
import os
from pathlib import Path from pathlib import Path
import re
import sys import sys
import click import click
@ -94,7 +92,7 @@ _sort_options = [
help="Use filename date for media original date.", help="Use filename date for media original date.",
), ),
click.option( click.option(
'--use-file-dates', '--use-file-dates',
'-F', '-F',
default=False, default=False,
is_flag=True, is_flag=True,
@ -102,6 +100,7 @@ _sort_options = [
), ),
] ]
def print_help(command): def print_help(command):
click.echo(command.get_help(click.Context(command))) click.echo(command.get_help(click.Context(command)))
@ -127,7 +126,33 @@ def _get_paths(paths, root):
return paths, root return paths, root
@click.command('check') def _cli_get_location(collection):
gopt = collection.opt['Geolocation']
return GeoLocation(
{
'geocoder': gopt['geocoder'],
'prefer_english_names': gopt['prefer_english_names'],
'timeout': gopt['timeout'],
}
)
def _cli_sort(collection, src_paths, import_mode, remove_duplicates):
loc = _cli_get_location(collection)
path_format = collection.opt['Path']['path_format']
return collection.sort_files(
src_paths, path_format, loc, import_mode, remove_duplicates
)
@click.group()
def cli(**kwargs):
pass
@cli.command('check')
@add_options(_logger_options) @add_options(_logger_options)
@click.argument('path', required=True, nargs=1, type=click.Path()) @click.argument('path', required=True, nargs=1, type=click.Path())
def _check(**kwargs): def _check(**kwargs):
@ -152,7 +177,7 @@ def _check(**kwargs):
sys.exit(1) sys.exit(1)
@click.command('clean') @cli.command('clean')
@add_options(_logger_options) @add_options(_logger_options)
@add_options(_dry_run_options) @add_options(_dry_run_options)
@add_options(_filter_options) @add_options(_filter_options)
@ -202,9 +227,11 @@ def _clean(**kwargs):
}, },
) )
# TODO # os.path.join(
# TODO make function to remove duplicates
# path_format = collection.opt['Path']['path_format']
# summary = collection.sort_files( # summary = collection.sort_files(
# paths, remove_duplicates=kwargs['remove_duplicates'] # paths, path_format, None, remove_duplicates=kwargs['remove_duplicates']
# ) # )
if kwargs['path_string']: if kwargs['path_string']:
@ -229,7 +256,7 @@ def _clean(**kwargs):
sys.exit(1) sys.exit(1)
@click.command('compare') @cli.command('compare')
@add_options(_logger_options) @add_options(_logger_options)
@add_options(_dry_run_options) @add_options(_dry_run_options)
@add_options(_filter_options) @add_options(_filter_options)
@ -283,7 +310,7 @@ def _compare(**kwargs):
sys.exit(1) sys.exit(1)
@click.command('init') @cli.command('init')
@add_options(_logger_options) @add_options(_logger_options)
@click.argument('path', required=True, nargs=1, type=click.Path()) @click.argument('path', required=True, nargs=1, type=click.Path())
def _init(**kwargs): def _init(**kwargs):
@ -296,11 +323,7 @@ def _init(**kwargs):
collection = Collection(root) collection = Collection(root)
# TODO retrieve collection.opt loc = _cli_get_location(collection)
geocoder='Nominatim'
prefer_english_names=False
timeout=1
loc = GeoLocation(geocoder, prefer_english_names, timeout)
summary = collection.init(loc) summary = collection.init(loc)
@ -308,7 +331,7 @@ def _init(**kwargs):
summary.print() summary.print()
@click.command('import') @cli.command('import')
@add_options(_logger_options) @add_options(_logger_options)
@add_options(_input_options) @add_options(_input_options)
@add_options(_dry_run_options) @add_options(_dry_run_options)
@ -333,11 +356,6 @@ def _import(**kwargs):
src_paths, root = _get_paths(kwargs['src'], kwargs['dest']) src_paths, root = _get_paths(kwargs['src'], kwargs['dest'])
if kwargs['copy']:
import_mode = 'copy'
else:
import_mode = 'move'
collection = Collection( collection = Collection(
root, root,
{ {
@ -351,19 +369,16 @@ def _import(**kwargs):
'glob': kwargs['glob'], 'glob': kwargs['glob'],
'dry_run': kwargs['dry_run'], 'dry_run': kwargs['dry_run'],
'interactive': kwargs['interactive'], 'interactive': kwargs['interactive'],
'path_format': kwargs['path_format'],
} }
) )
# TODO retrieve collection.opt if kwargs['copy']:
# Use loc function import_mode = 'copy'
geocoder='Nominatim' else:
prefer_english_names=False import_mode = 'move'
timeout=1 summary = _cli_sort(collection, src_paths, import_mode, kwargs['remove_duplicates'])
loc = GeoLocation(geocoder, prefer_english_names, timeout)
summary = collection.sort_files(
src_paths, kwargs['path_format'], loc, import_mode, kwargs['remove_duplicates']
)
if log_level < 30: if log_level < 30:
summary.print() summary.print()
@ -371,7 +386,8 @@ def _import(**kwargs):
if summary.errors: if summary.errors:
sys.exit(1) sys.exit(1)
@click.command('sort')
@cli.command('sort')
@add_options(_logger_options) @add_options(_logger_options)
@add_options(_input_options) @add_options(_input_options)
@add_options(_dry_run_options) @add_options(_dry_run_options)
@ -414,15 +430,7 @@ def _sort(**kwargs):
} }
) )
# TODO retrieve collection.opt summary = _cli_sort(collection, paths, False, kwargs['remove_duplicates'])
geocoder='Nominatim'
prefer_english_names=False
timeout=1
loc = GeoLocation(geocoder, prefer_english_names, timeout)
summary = collection.sort_files(
paths, kwargs['path_format'], loc, kwargs['remove_duplicates']
)
if kwargs['clean']: if kwargs['clean']:
collection.remove_empty_folders(root) collection.remove_empty_folders(root)
@ -434,7 +442,7 @@ def _sort(**kwargs):
sys.exit(1) sys.exit(1)
@click.command('update') @cli.command('update')
@add_options(_logger_options) @add_options(_logger_options)
@click.argument('path', required=True, nargs=1, type=click.Path()) @click.argument('path', required=True, nargs=1, type=click.Path())
def _update(**kwargs): def _update(**kwargs):
@ -445,26 +453,13 @@ def _update(**kwargs):
log_level = log.get_level(kwargs['verbose']) log_level = log.get_level(kwargs['verbose'])
log.console(LOG, level=log_level) log.console(LOG, level=log_level)
geocoder='Nominatim'
prefer_english_names=False
timeout=1
loc = GeoLocation(geocoder, prefer_english_names, timeout)
collection = Collection(root) collection = Collection(root)
loc = _cli_get_location(collection)
summary = collection.update(loc) summary = collection.update(loc)
if log_level < 30: if log_level < 30:
summary.print() summary.print()
@click.group() if __name__ == '__main__':
def main(**kwargs): cli()
pass
main.add_command(_clean)
main.add_command(_check)
main.add_command(_compare)
main.add_command(_init)
main.add_command(_import)
main.add_command(_sort)
main.add_command(_update)

View File

@ -58,9 +58,9 @@ class FPath:
def get_early_morning_photos_date(self, date, mask): def get_early_morning_photos_date(self, date, mask):
"""check for early hour photos to be grouped with previous day""" """check for early hour photos to be grouped with previous day"""
for i in '%H', '%M', '%S','%I', '%p', '%f': for i in '%H', '%M', '%S', '%I', '%p', '%f':
# D'ont change date format if datestring contain hour, minutes or seconds.
if i in mask: if i in mask:
# D'ont change date format if datestring contain hour, minutes or seconds...
return date.strftime(mask) return date.strftime(mask)
if date.hour < self.day_begins: if date.hour < self.day_begins:
@ -127,6 +127,7 @@ class FPath:
# Each item has its own custom logic and we evaluate a single item and return # Each item has its own custom logic and we evaluate a single item and return
# the evaluated string. # the evaluated string.
part = '' part = ''
filename = metadata['filename'] filename = metadata['filename']
stem = os.path.splitext(filename)[0] stem = os.path.splitext(filename)[0]
if item == 'stem': if item == 'stem':
@ -515,7 +516,6 @@ class SortMedias:
else: else:
self.summary.append('sort', False, src_path, dest_path) self.summary.append('sort', False, src_path, dest_path)
def sort_file(self, src_path, dest_path, metadata, imp=False): def sort_file(self, src_path, dest_path, metadata, imp=False):
"""Sort file and register it to db""" """Sort file and register it to db"""
if imp == 'copy': if imp == 'copy':
@ -545,7 +545,7 @@ class SortMedias:
directory_path = self.root / relpath directory_path = self.root / relpath
parts = directory_path.relative_to(self.root).parts parts = directory_path.relative_to(self.root).parts
for i, _ in enumerate(parts): for i, _ in enumerate(parts):
dir_path = self.root / Path(*parts[0 : i + 1]) dir_path = self.root / Path(*parts[0: i + 1])
if dir_path.is_file(): if dir_path.is_file():
self.log.warning(f'Target directory {dir_path} is a file') self.log.warning(f'Target directory {dir_path} is a file')
# Rename the src_file # Rename the src_file
@ -664,8 +664,9 @@ class SortMedias:
pass pass
if conflicts != []: if conflicts != []:
for files_data, conflict in self._solve_conflicts(conflicts, for files_data, conflict in self._solve_conflicts(
remove_duplicates): conflicts, remove_duplicates
):
src_path, dest_path, metadata = files_data src_path, dest_path, metadata = files_data
if not conflict: if not conflict:
@ -746,7 +747,7 @@ class Collection(SortMedias):
def get_config_options(self): def get_config_options(self):
"""Get collection config""" """Get collection config"""
config = Config(self.root.joinpath('.ordigi', 'ordigi.conf')) config = Config(self.root.joinpath('.ordigi', 'ordigi.conf'))
return config.get_config_options() return config.get_config_options()
@ -760,7 +761,7 @@ class Collection(SortMedias):
exclude = self.exclude exclude = self.exclude
paths = Paths( paths = Paths(
filters = { filters={
'exclude': exclude, 'exclude': exclude,
'extensions': None, 'extensions': None,
'glob': '**/*', 'glob': '**/*',
@ -839,7 +840,7 @@ class Collection(SortMedias):
metadata['src_path'] = row['SrcPath'] metadata['src_path'] = row['SrcPath']
# Check if row FilePath is a subpath of relpath # Check if row FilePath is a subpath of relpath
if relpath.startswith(row['FilePath']): if relpath.startswith(row['FilePath']):
path = os.path.relpath(relpath, row['FilePath']) path = os.path.relpath(rlpath, row['FilePath'])
metadata['subdirs'] = row['Subdirs'] + path metadata['subdirs'] = row['Subdirs'] + path
metadata['Filename'] = row['Filename'] metadata['Filename'] = row['Filename']
break break
@ -859,7 +860,7 @@ class Collection(SortMedias):
checksum = utils.checksum(file_path) checksum = utils.checksum(file_path)
relpath = file_path.relative_to(self.root) relpath = file_path.relative_to(self.root)
if checksum == self.db.sqlite.get_checksum(relpath): if checksum == self.db.sqlite.get_checksum(relpath):
self.summary.append('check',True, file_path) self.summary.append('check', True, file_path)
else: else:
self.log.error('{file_path} is corrupted') self.log.error('{file_path} is corrupted')
self.summary.append('check', False, file_path) self.summary.append('check', False, file_path)
@ -933,9 +934,9 @@ class Collection(SortMedias):
return self.summary return self.summary
def sort_files( def sort_files(
self, src_dirs, path_format, loc, self, src_dirs, path_format, loc,
imp=False, remove_duplicates=False imp=False, remove_duplicates=False
): ):
""" """
Sort files into appropriate folder Sort files into appropriate folder
""" """

View File

@ -2,12 +2,10 @@ import json
import re import re
from configparser import RawConfigParser from configparser import RawConfigParser
from os import path
from ordigi import constants from ordigi import constants
from geopy.geocoders import options as gopt from geopy.geocoders import options as gopt
# TODO make one method???
def check_option(getoption): def check_option(getoption):
"""Check option type int or boolean""" """Check option type int or boolean"""
try: try:
@ -18,6 +16,7 @@ def check_option(getoption):
else: else:
return getoption return getoption
def check_json(getoption): def check_json(getoption):
"""Check if json string is valid""" """Check if json string is valid"""
try: try:
@ -28,6 +27,7 @@ def check_json(getoption):
else: else:
return getoption return getoption
def check_re(getoption): def check_re(getoption):
"""Check if regex string is valid""" """Check if regex string is valid"""
try: try:
@ -165,9 +165,9 @@ class Config:
if option == 'geocoder' and value in ('Nominatim',): if option == 'geocoder' and value in ('Nominatim',):
return self.conf[section][option] return self.conf[section][option]
if option == 'glob': if option == 'glob':
return self.conf[section][option]
if option == 'path_format':
return self.getre(section, option) return self.getre(section, option)
if option == 'path_format':
return self.conf[section][option]
if option in multi_options: if option in multi_options:
return set(self.getjson(section, option)) return set(self.getjson(section, option))

View File

@ -8,6 +8,7 @@ from pathlib import Path
#: If True, debug messages will be printed. #: If True, debug messages will be printed.
debug = False debug = False
# Ordigi settings directory. # Ordigi settings directory.
def get_config_dir(name): def get_config_dir(name):
if 'XDG_CONFIG_HOME' in environ: if 'XDG_CONFIG_HOME' in environ:
@ -19,6 +20,7 @@ def get_config_dir(name):
return confighome / name return confighome / name
APPLICATION_DIRECTORY = get_config_dir('ordigi') APPLICATION_DIRECTORY = get_config_dir('ordigi')
DEFAULT_PATH = '{%Y-%m-%b}/{album}|{city}' DEFAULT_PATH = '{%Y-%m-%b}/{album}|{city}'

View File

@ -30,4 +30,10 @@ exclude =
[options.entry_points] [options.entry_points]
console_scripts = console_scripts =
ordigi = ordigi.cli:main ordigi = ordigi.cli:cli
[flake8]
[pycodestyle]
max-line-length = 88

View File

@ -217,7 +217,7 @@ class TestCollection:
src_checksum = utils.checksum(src_path) src_checksum = utils.checksum(src_path)
summary = collection.sort_file( summary = collection.sort_file(
src_path, dest_path, media.metadata, imp=imp src_path, dest_path, media.metadata, imp=imp
) )
assert not summary.errors assert not summary.errors
# Ensure files remain the same # Ensure files remain the same
assert collection._checkcomp(dest_path, src_checksum) assert collection._checkcomp(dest_path, src_checksum)