Refactoring collection options (3)
This commit is contained in:
parent
27af9bb55e
commit
7688d0e7c4
|
@ -184,7 +184,6 @@ def _check(**kwargs):
|
|||
def _clean(**kwargs):
|
||||
"""Remove empty folders"""
|
||||
|
||||
dry_run = kwargs['dry_run']
|
||||
folders = kwargs['folders']
|
||||
log_level = log.get_level(kwargs['verbose'])
|
||||
log.console(LOG, level=log_level)
|
||||
|
@ -195,10 +194,12 @@ def _clean(**kwargs):
|
|||
|
||||
collection = Collection(
|
||||
root,
|
||||
dry_run=dry_run,
|
||||
exclude=kwargs['exclude'],
|
||||
extensions=kwargs['ext'],
|
||||
glob=kwargs['glob'],
|
||||
{
|
||||
"dry_run": kwargs['dry_run'],
|
||||
"exclude": kwargs['exclude'],
|
||||
"extensions": kwargs['ext'],
|
||||
"glob": kwargs['glob'],
|
||||
},
|
||||
)
|
||||
|
||||
# TODO
|
||||
|
@ -253,7 +254,6 @@ def _compare(**kwargs):
|
|||
Sort similar images in directories
|
||||
"""
|
||||
|
||||
dry_run = kwargs['dry_run']
|
||||
subdirs = kwargs['subdirs']
|
||||
root = kwargs['collection']
|
||||
|
||||
|
@ -263,10 +263,12 @@ def _compare(**kwargs):
|
|||
|
||||
collection = Collection(
|
||||
root,
|
||||
exclude=kwargs['exclude'],
|
||||
extensions=kwargs['ext'],
|
||||
glob=kwargs['glob'],
|
||||
dry_run=dry_run,
|
||||
{
|
||||
"exclude": kwargs['exclude'],
|
||||
"extensions": kwargs['ext'],
|
||||
"glob": kwargs['glob'],
|
||||
"dry_run": kwargs['dry_run'],
|
||||
},
|
||||
)
|
||||
|
||||
for path in paths:
|
||||
|
@ -338,16 +340,18 @@ def _import(**kwargs):
|
|||
|
||||
collection = Collection(
|
||||
root,
|
||||
kwargs['album_from_folder'],
|
||||
False,
|
||||
kwargs['dry_run'],
|
||||
kwargs['exclude'],
|
||||
kwargs['ext'],
|
||||
kwargs['glob'],
|
||||
kwargs['interactive'],
|
||||
kwargs['ignore_tags'],
|
||||
kwargs['use_date_filename'],
|
||||
kwargs['use_file_dates'],
|
||||
{
|
||||
'album_from_folder': kwargs['album_from_folder'],
|
||||
'cache': False,
|
||||
'ignore_tags': kwargs['ignore_tags'],
|
||||
'use_date_filename': kwargs['use_date_filename'],
|
||||
'use_file_dates': kwargs['use_file_dates'],
|
||||
'exclude': kwargs['exclude'],
|
||||
'extensions': kwargs['ext'],
|
||||
'glob': kwargs['glob'],
|
||||
'dry_run': kwargs['dry_run'],
|
||||
'interactive': kwargs['interactive'],
|
||||
}
|
||||
)
|
||||
|
||||
# TODO retrieve collection.opt
|
||||
|
@ -396,16 +400,18 @@ def _sort(**kwargs):
|
|||
|
||||
collection = Collection(
|
||||
root,
|
||||
kwargs['album_from_folder'],
|
||||
cache,
|
||||
kwargs['dry_run'],
|
||||
kwargs['exclude'],
|
||||
kwargs['ext'],
|
||||
kwargs['glob'],
|
||||
kwargs['interactive'],
|
||||
kwargs['ignore_tags'],
|
||||
kwargs['use_date_filename'],
|
||||
kwargs['use_file_dates'],
|
||||
{
|
||||
'album_from_folder': kwargs['album_from_folder'],
|
||||
'cache': cache,
|
||||
'ignore_tags': kwargs['ignore_tags'],
|
||||
'use_date_filename': kwargs['use_date_filename'],
|
||||
'use_file_dates': kwargs['use_file_dates'],
|
||||
'exclude': kwargs['exclude'],
|
||||
'extensions': kwargs['ext'],
|
||||
'glob': kwargs['glob'],
|
||||
'dry_run': kwargs['dry_run'],
|
||||
'interactive': kwargs['interactive'],
|
||||
}
|
||||
)
|
||||
|
||||
# TODO retrieve collection.opt
|
||||
|
|
|
@ -308,28 +308,21 @@ class FileIO:
|
|||
class Paths:
|
||||
"""Get filtered files paths"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
exclude=None,
|
||||
extensions=None,
|
||||
glob='**/*',
|
||||
interactive=False,
|
||||
max_deep=None,
|
||||
):
|
||||
def __init__(self, filters, interactive=False):
|
||||
|
||||
# Options
|
||||
self.exclude = exclude
|
||||
self.filters = filters
|
||||
|
||||
if extensions and '%media' in extensions:
|
||||
extensions.remove('%media')
|
||||
self.extensions = extensions.union(Medias.extensions)
|
||||
else:
|
||||
self.extensions = extensions
|
||||
self.extensions = self.filters['extensions']
|
||||
if not self.extensions:
|
||||
self.extensions = set()
|
||||
elif '%media' in self.extensions:
|
||||
self.extensions.remove('%media')
|
||||
self.extensions = self.extensions.union(Medias.extensions)
|
||||
|
||||
self.glob = self.filters['glob']
|
||||
|
||||
self.glob = glob
|
||||
self.interactive = interactive
|
||||
self.log = LOG.getChild(self.__class__.__name__)
|
||||
self.max_deep = max_deep
|
||||
self.paths_list = []
|
||||
|
||||
# Attributes
|
||||
|
@ -382,10 +375,11 @@ class Paths:
|
|||
if path / '.ordigi' in file_path.parents:
|
||||
continue
|
||||
|
||||
if self.max_deep is not None:
|
||||
if level > self.max_deep:
|
||||
if self.filters['max_deep'] is not None:
|
||||
if level > self.filters['max_deep']:
|
||||
continue
|
||||
|
||||
self.exclude = self.filters['exclude']
|
||||
if self.exclude:
|
||||
matched = False
|
||||
for exclude in self.exclude:
|
||||
|
@ -695,34 +689,10 @@ class SortMedias:
|
|||
class Collection(SortMedias):
|
||||
"""Class of the media collection."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
root,
|
||||
album_from_folder=False,
|
||||
cache=False,
|
||||
dry_run=False,
|
||||
exclude=None,
|
||||
extensions=None,
|
||||
glob='**/*',
|
||||
interactive=False,
|
||||
ignore_tags=None,
|
||||
use_date_filename=False,
|
||||
use_file_dates=False,
|
||||
):
|
||||
def __init__(self, root, cli_options=None):
|
||||
|
||||
# TODO move to cli
|
||||
cli_options = {
|
||||
'album_from_folder': album_from_folder,
|
||||
'cache': cache,
|
||||
'dry_run': dry_run,
|
||||
'exclude': exclude,
|
||||
'extensions': extensions,
|
||||
'glob': '**/*',
|
||||
'interactive': interactive,
|
||||
'ignore_tags': ignore_tags,
|
||||
'use_date_filename': use_date_filename,
|
||||
'use_file_dates': use_file_dates,
|
||||
}
|
||||
if not cli_options:
|
||||
cli_options = {}
|
||||
|
||||
self.log = LOG.getChild(self.__class__.__name__)
|
||||
|
||||
|
@ -734,34 +704,30 @@ class Collection(SortMedias):
|
|||
self.root = root
|
||||
|
||||
# Get config options
|
||||
config = self.get_config()
|
||||
self.opt = config.get_options()
|
||||
self.opt = self.get_config_options()
|
||||
|
||||
# Set client options
|
||||
for option, value in cli_options.items():
|
||||
self.opt[option] = value
|
||||
self._set_cli_option('exclude', exclude)
|
||||
for section in self.opt:
|
||||
self.opt[section][option] = value
|
||||
|
||||
self.exclude = self.opt['Filters']['exclude']
|
||||
if not self.exclude:
|
||||
self.exclude = set()
|
||||
|
||||
self.db = CollectionDb(root)
|
||||
self.fileio = FileIO(self.opt['dry_run'])
|
||||
self.fileio = FileIO(self.opt['Terminal']['dry_run'])
|
||||
self.paths = Paths(
|
||||
self.opt['exclude'],
|
||||
self.opt['extensions'],
|
||||
self.opt['glob'],
|
||||
self.opt['interactive'],
|
||||
self.opt['max_deep'],
|
||||
self.opt['Filters'],
|
||||
interactive=self.opt['Terminal']['interactive'],
|
||||
)
|
||||
|
||||
self.medias = Medias(
|
||||
self.paths,
|
||||
root,
|
||||
self.opt['album_from_folder'],
|
||||
self.opt['cache'],
|
||||
self.opt['Exif'],
|
||||
self.db,
|
||||
self.opt['interactive'],
|
||||
self.opt['ignore_tags'],
|
||||
self.opt['use_date_filename'],
|
||||
self.opt['use_file_dates'],
|
||||
self.opt['Terminal']['interactive'],
|
||||
)
|
||||
|
||||
# Features
|
||||
|
@ -770,30 +736,37 @@ class Collection(SortMedias):
|
|||
self.medias,
|
||||
root,
|
||||
self.db,
|
||||
self.opt['dry_run'],
|
||||
self.opt['interactive'],
|
||||
self.opt['Terminal']['dry_run'],
|
||||
self.opt['Terminal']['interactive'],
|
||||
)
|
||||
|
||||
# Attributes
|
||||
self.summary = Summary(self.root)
|
||||
self.theme = request.load_theme()
|
||||
|
||||
def get_config(self):
|
||||
def get_config_options(self):
|
||||
"""Get collection config"""
|
||||
return Config(self.root.joinpath('.ordigi', 'ordigi.conf'))
|
||||
config = Config(self.root.joinpath('.ordigi', 'ordigi.conf'))
|
||||
|
||||
def _set_cli_option(self, option, cli_option):
|
||||
return config.get_config_options()
|
||||
|
||||
def _set_option(self, section, option, cli_option):
|
||||
"""if client option is set overwrite collection option value"""
|
||||
if cli_option:
|
||||
self.opt['option'] = cli_option
|
||||
self.opt[section][option] = cli_option
|
||||
|
||||
def get_collection_files(self, exclude=True):
|
||||
if exclude:
|
||||
exclude = self.paths.exclude
|
||||
exclude = self.exclude
|
||||
|
||||
paths = Paths(
|
||||
exclude,
|
||||
interactive=self.opt['interactive'],
|
||||
filters = {
|
||||
'exclude': exclude,
|
||||
'extensions': None,
|
||||
'glob': '**/*',
|
||||
'max_deep': None,
|
||||
},
|
||||
interactive=self.opt['Terminal']['interactive'],
|
||||
)
|
||||
for file_path in paths.get_files(self.root):
|
||||
yield file_path
|
||||
|
@ -905,7 +878,7 @@ class Collection(SortMedias):
|
|||
"""Remove excluded files in collection"""
|
||||
# get all files
|
||||
for file_path in self.get_collection_files(exclude=False):
|
||||
for exclude in self.paths.exclude:
|
||||
for exclude in self.exclude:
|
||||
if fnmatch(file_path, exclude):
|
||||
self.fileio.remove(file_path)
|
||||
self.summary.append('remove', True, file_path)
|
||||
|
@ -953,7 +926,7 @@ class Collection(SortMedias):
|
|||
files = os.listdir(directory)
|
||||
if len(files) == 0 and remove_root:
|
||||
self.log.info(f"Removing empty folder: {directory}")
|
||||
if not self.opt['dry_run']:
|
||||
if not self.opt['Terminal']['dry_run']:
|
||||
os.rmdir(directory)
|
||||
self.summary.append('remove', True, directory)
|
||||
|
||||
|
@ -970,13 +943,13 @@ class Collection(SortMedias):
|
|||
self._init_check_db(loc)
|
||||
|
||||
# if path format client option is set overwrite it
|
||||
self._set_cli_option('path_format', path_format)
|
||||
self._set_option('Path', 'path_format', path_format)
|
||||
|
||||
# Get medias data
|
||||
subdirs = set()
|
||||
for src_path, metadata in self.medias.get_metadatas(src_dirs, imp=imp, loc=loc):
|
||||
# Get the destination path according to metadata
|
||||
fpath = FPath(path_format, self.opt['day_begins'])
|
||||
fpath = FPath(path_format, self.opt['Path']['day_begins'])
|
||||
metadata['file_path'] = fpath.get_path(metadata)
|
||||
subdirs.add(src_path.parent)
|
||||
|
||||
|
|
|
@ -42,36 +42,6 @@ def check_re(getoption):
|
|||
class Config:
|
||||
"""Manage config file"""
|
||||
|
||||
# Initialize with default options
|
||||
options: dict = {
|
||||
'Console': {
|
||||
'dry_run': False,
|
||||
'interactive': False,
|
||||
},
|
||||
'Database': {
|
||||
'cache': False,
|
||||
'album_from_folder': False,
|
||||
'ignore_tags': None,
|
||||
'use_date_filename': False,
|
||||
'use_file_dates': False,
|
||||
},
|
||||
'Filters': {
|
||||
'exclude': None,
|
||||
'extensions': None,
|
||||
'glob': '**/*',
|
||||
'max_deep': None,
|
||||
},
|
||||
'Geolocation': {
|
||||
'geocoder': constants.DEFAULT_GEOCODER,
|
||||
'prefer_english_names': False,
|
||||
'timeout': gopt.default_timeout,
|
||||
},
|
||||
'Path': {
|
||||
'day_begins': 0,
|
||||
'path_format': constants.DEFAULT_PATH_FORMAT,
|
||||
},
|
||||
}
|
||||
|
||||
def __init__(self, conf_path=constants.CONFIG_FILE, conf=None):
|
||||
self.conf_path = conf_path
|
||||
if conf is None:
|
||||
|
@ -83,6 +53,39 @@ class Config:
|
|||
else:
|
||||
self.conf = conf
|
||||
|
||||
self.options = self.set_default_options()
|
||||
|
||||
def set_default_options(self) -> dict:
|
||||
# Initialize with default options
|
||||
return {
|
||||
'Exif': {
|
||||
'album_from_folder': False,
|
||||
'cache': False,
|
||||
'ignore_tags': None,
|
||||
'use_date_filename': False,
|
||||
'use_file_dates': False,
|
||||
},
|
||||
'Filters': {
|
||||
'exclude': None,
|
||||
'extensions': None,
|
||||
'glob': '**/*',
|
||||
'max_deep': None,
|
||||
},
|
||||
'Geolocation': {
|
||||
'geocoder': constants.DEFAULT_GEOCODER,
|
||||
'prefer_english_names': False,
|
||||
'timeout': gopt.default_timeout,
|
||||
},
|
||||
'Path': {
|
||||
'day_begins': 0,
|
||||
'path_format': constants.DEFAULT_PATH_FORMAT,
|
||||
},
|
||||
'Terminal': {
|
||||
'dry_run': False,
|
||||
'interactive': False,
|
||||
},
|
||||
}
|
||||
|
||||
def write(self, conf):
|
||||
with open(self.conf_path, 'w') as conf_file:
|
||||
conf.write(conf_file)
|
||||
|
@ -125,7 +128,7 @@ class Config:
|
|||
return re.compile(self.conf.get(section, option))
|
||||
getre = check_re(_getre)
|
||||
|
||||
def get_option(self, section, option):
|
||||
def get_config_option(self, section, option):
|
||||
bool_options = {
|
||||
'cache',
|
||||
'dry_run',
|
||||
|
@ -176,16 +179,13 @@ class Config:
|
|||
|
||||
return value
|
||||
|
||||
def get_options(self) -> dict:
|
||||
def get_config_options(self) -> dict:
|
||||
"""Get config options"""
|
||||
|
||||
old_options = {}
|
||||
for section in self.options:
|
||||
for option in self.options[section]:
|
||||
# Option is in section
|
||||
# TODO make a function
|
||||
value = self.get_option(section, option)
|
||||
old_options[option] = value
|
||||
value = self.get_config_option(section, option)
|
||||
self.options[section][option] = value
|
||||
|
||||
return old_options
|
||||
return self.options
|
||||
|
|
|
@ -611,13 +611,9 @@ class Medias:
|
|||
self,
|
||||
paths,
|
||||
root,
|
||||
album_from_folder=False,
|
||||
cache=False,
|
||||
exif_options,
|
||||
db=None,
|
||||
interactive=False,
|
||||
ignore_tags=None,
|
||||
use_date_filename=False,
|
||||
use_file_dates=False,
|
||||
):
|
||||
|
||||
# Modules
|
||||
|
@ -628,13 +624,11 @@ class Medias:
|
|||
self.root = root
|
||||
|
||||
# Options
|
||||
self.cache = cache
|
||||
self.album_from_folder = album_from_folder
|
||||
self.ignore_tags = ignore_tags
|
||||
self.exif_opt = exif_options
|
||||
self.album_from_folder = self.exif_opt['album_from_folder']
|
||||
self.ignore_tags = self.exif_opt['ignore_tags']
|
||||
self.interactive = interactive
|
||||
self.log = LOG.getChild(self.__class__.__name__)
|
||||
self.use_date_filename = use_date_filename
|
||||
self.use_file_dates = use_file_dates
|
||||
|
||||
# Attributes
|
||||
# List to store medias datas
|
||||
|
@ -648,16 +642,17 @@ class Medias:
|
|||
self.album_from_folder,
|
||||
self.ignore_tags,
|
||||
self.interactive,
|
||||
self.use_date_filename,
|
||||
self.use_file_dates,
|
||||
self.exif_opt['use_date_filename'],
|
||||
self.exif_opt['use_file_dates'],
|
||||
)
|
||||
|
||||
return media
|
||||
|
||||
def get_metadata(self, file_path, src_dir, loc=None):
|
||||
media = self.get_media(file_path, src_dir)
|
||||
media.get_metadata(self.root, loc, self.db.sqlite,
|
||||
self.cache)
|
||||
media.get_metadata(
|
||||
self.root, loc, self.db.sqlite, self.exif_opt['cache']
|
||||
)
|
||||
|
||||
return media.metadata
|
||||
|
||||
|
|
|
@ -137,7 +137,8 @@ class TestCollection:
|
|||
assert summary.success_table.sum('sort') == nb
|
||||
|
||||
def test_sort_files(self, tmp_path):
|
||||
collection = Collection(tmp_path, album_from_folder=True)
|
||||
cli_options = {'album_from_folder': True}
|
||||
collection = Collection(tmp_path, cli_options=cli_options)
|
||||
loc = GeoLocation()
|
||||
summary = collection.sort_files([self.src_path],
|
||||
self.path_format, loc, imp='copy')
|
||||
|
@ -150,14 +151,20 @@ class TestCollection:
|
|||
assert not summary.errors
|
||||
|
||||
# check if album value are set
|
||||
paths = Paths(glob='**/*').get_files(tmp_path)
|
||||
filters = {
|
||||
'exclude': None,
|
||||
'extensions': None,
|
||||
'glob': '**/*',
|
||||
'max_deep': None,
|
||||
}
|
||||
paths = Paths(filters).get_files(tmp_path)
|
||||
for file_path in paths:
|
||||
if '.db' not in str(file_path):
|
||||
media = Media(file_path, tmp_path, album_from_folder=True)
|
||||
for value in ReadExif(file_path).get_key_values('album'):
|
||||
assert value != '' or None
|
||||
|
||||
collection = Collection(tmp_path, album_from_folder=True)
|
||||
collection = Collection(tmp_path, cli_options=cli_options)
|
||||
# Try to change path format and sort files again
|
||||
path = '{city}/{%Y}-{name}.%l{ext}'
|
||||
summary = collection.sort_files([tmp_path],
|
||||
|
@ -222,8 +229,13 @@ class TestCollection:
|
|||
shutil.copyfile(dest_path, src_path)
|
||||
|
||||
def test_get_files(self):
|
||||
exclude={'**/*.dng',}
|
||||
paths = Paths(exclude=exclude, max_deep=1)
|
||||
filters = {
|
||||
'exclude': {'**/*.dng',},
|
||||
'extensions': None,
|
||||
'glob': '**/*',
|
||||
'max_deep': 1,
|
||||
}
|
||||
paths = Paths(filters)
|
||||
paths = list(paths.get_files(self.src_path))
|
||||
assert len(paths) == 9
|
||||
assert Path(self.src_path, 'test_exif/photo.dng') not in paths
|
||||
|
|
|
@ -58,8 +58,8 @@ class TestConfig:
|
|||
# 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}'
|
||||
|
||||
def test_get_options(self, conf):
|
||||
def test_get_config_options(self, conf):
|
||||
config = Config(conf=conf)
|
||||
options = config.get_options()
|
||||
options = config.get_config_options()
|
||||
assert isinstance(options, dict)
|
||||
# assert isinstance(options['Path'], dict)
|
||||
|
|
Loading…
Reference in New Issue