Coverage for roter/__init__.py: 96.30%
48 statements
« prev ^ index » next coverage.py v7.5.4, created at 2024-06-24 19:21:34 +00:00
« prev ^ index » next coverage.py v7.5.4, created at 2024-06-24 19:21:34 +00:00
1"""Rotate and combine tables (Danish: Roter og kombiner borde)."""
2import datetime as dti
3import logging
4import os
5import pathlib
6from typing import no_type_check
8# [[[fill git_describe()]]]
9__version__ = '2024.6.25+parent.g6fa266b5'
10# [[[end]]] (checksum: b29c576c4af1129e2573d3775dcb941e)
11__version_info__ = tuple(
12 e if '-' not in e else e.split('-')[0] for part in __version__.split('+') for e in part.split('.') if e != 'parent'
13)
15APP_ALIAS = str(pathlib.Path(__file__).parent.name)
16APP_ENV = APP_ALIAS.upper()
17APP_NAME = locals()['__doc__']
18DEBUG = bool(os.getenv(f'{APP_ENV}_DEBUG', ''))
19VERBOSE = bool(os.getenv(f'{APP_ENV}_VERBOSE', ''))
20QUIET = False
21STRICT = bool(os.getenv(f'{APP_ENV}_STRICT', ''))
22ENCODING = 'utf-8'
23ENCODING_ERRORS_POLICY = 'ignore'
24DEFAULT_CONFIG_NAME = f'.{APP_ALIAS}.json'
26APP_VERSION = __version__
27COMMA = ','
28DEFAULT_LF_ONLY = 'YES'
29KNOWN_FORMATS = ('json', 'xml', 'yaml')
30KNOWN_KEY_FUNCTIONS = ('blake2', 'elf', 'md5')
31TS_FORMAT = '%Y-%m-%d %H:%M:%S.%f +00:00'
32VERSION_INFO = __version_info__
34log = logging.getLogger() # Module level logger is sufficient
35LOG_FOLDER = pathlib.Path('logs')
36LOG_FILE = f'{APP_ALIAS}.log'
37LOG_PATH = pathlib.Path(LOG_FOLDER, LOG_FILE) if LOG_FOLDER.is_dir() else pathlib.Path(LOG_FILE)
38LOG_LEVEL = logging.INFO
40TS_FORMAT_LOG = '%Y-%m-%dT%H:%M:%S'
41TS_FORMAT_PAYLOADS = '%Y-%m-%d %H:%M:%S.%f UTC'
43MARKERS = (
44 '<!--{{inject-combined->}}-->,<!--{{<-inject-combined->}}-->'
45 ',<!--{{inject-inverted->}}-->,<!--{{<-inject-inverted->}}-->'
46)
48CHILD_ATTRIBUTES = '1,Child,Children'
49PARENT_ATTRIBUTES = '2,Parent,Parents'
52__all__: list[str] = [
53 'APP_ALIAS',
54 'APP_ENV',
55 'APP_NAME',
56 'APP_VERSION',
57 'CHILD_ATTRIBUTES',
58 'ENCODING',
59 'MARKERS',
60 'PARENT_ATTRIBUTES',
61 'TS_FORMAT_PAYLOADS',
62 'VERSION_INFO',
63 'log',
64 'parse_csl_preserve_case',
65]
68def parse_csl_preserve_case(csl: str) -> list[str]:
69 """DRY."""
70 return [fmt.strip() for fmt in csl.split(COMMA) if fmt.strip()]
73@no_type_check
74def formatTime_RFC3339(self, record, datefmt=None):
75 """HACK A DID ACK we could inject .astimezone() to localize ..."""
76 return dti.datetime.fromtimestamp(record.created, dti.timezone.utc).isoformat()
79@no_type_check
80def init_logger(name=None, level=None):
81 """Initialize module level logger"""
82 global log # pylint: disable=global-statement
84 log_format = {
85 'format': '%(asctime)s %(levelname)s [%(name)s]: %(message)s',
86 'datefmt': TS_FORMAT_LOG,
87 # 'filename': LOG_PATH,
88 'level': LOG_LEVEL if level is None else level,
89 }
90 logging.Formatter.formatTime = formatTime_RFC3339
91 logging.basicConfig(**log_format)
92 log = logging.getLogger(APP_ENV if name is None else name)
93 log.propagate = True
96init_logger(name=APP_ENV, level=logging.DEBUG if DEBUG else None)