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

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 

7 

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) 

14 

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' 

25 

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__ 

33 

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 

39 

40TS_FORMAT_LOG = '%Y-%m-%dT%H:%M:%S' 

41TS_FORMAT_PAYLOADS = '%Y-%m-%d %H:%M:%S.%f UTC' 

42 

43MARKERS = ( 

44 '<!--{{inject-combined->}}-->,<!--{{<-inject-combined->}}-->' 

45 ',<!--{{inject-inverted->}}-->,<!--{{<-inject-inverted->}}-->' 

46) 

47 

48CHILD_ATTRIBUTES = '1,Child,Children' 

49PARENT_ATTRIBUTES = '2,Parent,Parents' 

50 

51 

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] 

66 

67 

68def parse_csl_preserve_case(csl: str) -> list[str]: 

69 """DRY.""" 

70 return [fmt.strip() for fmt in csl.split(COMMA) if fmt.strip()] 

71 

72 

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() 

77 

78 

79@no_type_check 

80def init_logger(name=None, level=None): 

81 """Initialize module level logger""" 

82 global log # pylint: disable=global-statement 

83 

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 

94 

95 

96init_logger(name=APP_ENV, level=logging.DEBUG if DEBUG else None)