ordigi/ordigi/config.py

193 lines
5.1 KiB
Python

import json
import re
from configparser import RawConfigParser
from ordigi import constants
from geopy.geocoders import options as gopt
def check_option(getoption):
"""Check option type int or boolean"""
try:
getoption
except ValueError as e:
# TODO
return None
else:
return getoption
def check_json(getoption):
"""Check if json string is valid"""
try:
getoption
except json.JSONDecodeError as e:
# TODO
return None
else:
return getoption
def check_re(getoption):
"""Check if regex string is valid"""
try:
getoption
except re.error as e:
# TODO
return None
else:
return getoption
class Config:
"""Manage config file"""
def __init__(self, conf_path=constants.CONFIG_FILE, conf=None):
self.conf_path = conf_path
if conf is None:
self.conf = self.load_config()
if self.conf == {}:
# Fallback to default config
self.conf_path = constants.CONFIG_FILE
self.conf = self.load_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': True,
'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)
return True
return False
def load_config(self):
if not self.conf_path.exists():
return {}
conf = RawConfigParser()
conf.read(self.conf_path)
return conf
def is_option(self, section, option):
"""Get ConfigParser options"""
if section in self.conf and option in self.conf[section]:
return True
return False
@check_option
def _getboolean(self, section, option):
return self.conf.getboolean(section, option)
getboolean = check_option(_getboolean)
@check_option
def _getint(self, section, option):
return self.conf.getint(section, option)
getint = check_option(_getint)
@check_json
def _getjson(self, section, option):
return json.loads(self.conf.get(section, option))
getjson = check_json(_getjson)
@check_re
def _getre(self, section, option):
return re.compile(self.conf.get(section, option))
getre = check_re(_getre)
def get_config_option(self, section, option):
bool_options = {
'cache',
'dry_run',
'prefer_english_names',
'album_from_folder',
'interactive',
'use_date_filename',
'use_file_dates',
}
int_options = {
'day_begins',
'max_deep',
'timeout',
}
string_options = {
'glob',
'geocoder',
}
multi_options = {
'exclude',
'extensions',
'ignore_tags',
}
value = self.options[section][option]
if self.is_option(section, option):
if option in bool_options:
return self.getboolean(section, option)
if option in int_options:
return self.getint(section, option)
if option == 'geocoder' and value in ('Nominatim',):
return self.conf[section][option]
if option == 'glob':
return self.getre(section, option)
if option == 'path_format':
return self.conf[section][option]
if option in multi_options:
return set(self.getjson(section, option))
return value
if option == 'path_format':
if self.is_option('Path', 'name') and self.is_option('Path', 'dirs_path'):
# Path format is split in two parts
value = self.conf['Path']['dirs_path'] + '/' + self.conf['Path']['name']
return value
def get_config_options(self) -> dict:
"""Get config options"""
for section in self.options:
for option in self.options[section]:
# Option is in section
value = self.get_config_option(section, option)
self.options[section][option] = value
return self.options