summaryrefslogtreecommitdiff
path: root/src/home/config
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2021-11-27 16:17:05 +0300
committerEvgeny Zinoviev <me@ch1p.io>2022-04-24 01:33:04 +0300
commitc412bf2ee0a3fbf9032fc32a26837d4fbc7585c5 (patch)
tree5cca6bcab79331ad82cab4219c7692b9dd4eea21 /src/home/config
initial public
Diffstat (limited to 'src/home/config')
-rw-r--r--src/home/config/__init__.py1
-rw-r--r--src/home/config/config.py110
2 files changed, 111 insertions, 0 deletions
diff --git a/src/home/config/__init__.py b/src/home/config/__init__.py
new file mode 100644
index 0000000..d4b1c27
--- /dev/null
+++ b/src/home/config/__init__.py
@@ -0,0 +1 @@
+from .config import ConfigStore, config, is_development_mode
diff --git a/src/home/config/config.py b/src/home/config/config.py
new file mode 100644
index 0000000..75cfc3a
--- /dev/null
+++ b/src/home/config/config.py
@@ -0,0 +1,110 @@
+import toml
+import logging
+import os
+
+from os.path import join, isdir, isfile
+from typing import Optional, Any, MutableMapping
+from argparse import ArgumentParser
+
+
+def _get_config_path(name: str) -> str:
+ dirname = join(os.environ['HOME'], '.config', name)
+ filename = join(os.environ['HOME'], '.config', f'{name}.toml')
+ if isdir(dirname):
+ return join(dirname, 'config.toml')
+ elif isfile(filename):
+ return filename
+ else:
+ raise IOError(f'configuration file not found (tried {dirname}/config.toml and {filename})')
+
+
+class ConfigStore:
+ data: MutableMapping[str, Any]
+ app_name: Optional[str]
+
+ def __int__(self):
+ self.data = {}
+ self.app_name = None
+
+ def load(self, name: Optional[str] = None,
+ use_cli=True,
+ parser: ArgumentParser = None):
+ self.app_name = name
+
+ if (name is None) and (not use_cli):
+ raise RuntimeError('either config name must be none or use_cli must be True')
+
+ log_default_fmt = False
+ log_file = None
+ log_verbose = False
+
+ path = None
+ if use_cli:
+ if parser is None:
+ parser = ArgumentParser()
+ parser.add_argument('--config', type=str, required=name is None,
+ help='Path to the config in TOML format')
+ parser.add_argument('--verbose', action='store_true')
+ parser.add_argument('--log-file', type=str)
+ parser.add_argument('--log-default-fmt', action='store_true')
+ args = parser.parse_args()
+
+ if args.config:
+ path = args.config
+ if args.verbose:
+ log_verbose = True
+ if args.log_file:
+ log_file = args.log_file
+ if args.log_default_fmt:
+ log_default_fmt = args.log_default_fmt
+
+ if name and path is None:
+ path = _get_config_path(name)
+
+ self.data = toml.load(path)
+
+ if 'logging' in self:
+ if not log_file and 'file' in self['logging']:
+ log_file = self['logging']['file']
+ if log_default_fmt and 'default_fmt' in self['logging']:
+ log_default_fmt = self['logging']['default_fmt']
+
+ setup_logging(log_verbose, log_file, log_default_fmt)
+
+ if use_cli:
+ return args
+
+ def __getitem__(self, key):
+ return self.data[key]
+
+ def __setitem__(self, key, value):
+ raise NotImplementedError('overwriting config values is prohibited')
+
+ def __contains__(self, key):
+ return key in self.data
+
+
+config = ConfigStore()
+
+
+def is_development_mode() -> bool:
+ if 'FLASK_ENV' in os.environ and os.environ['FLASK_ENV'] == 'development':
+ return True
+
+ return ('logging' in config) and ('verbose' in config['logging']) and (config['logging']['verbose'] is True)
+
+
+def setup_logging(verbose=False, log_file=None, default_fmt=False):
+ logging_level = logging.INFO
+ if is_development_mode() or verbose:
+ logging_level = logging.DEBUG
+
+ log_config = {'level': logging_level}
+ if not default_fmt:
+ log_config['format'] = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
+
+ if log_file is not None:
+ log_config['filename'] = log_file
+ log_config['encoding'] = 'utf-8'
+
+ logging.basicConfig(**log_config)