Coverage for muuntaa/__init__.py: 100.00%

44 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-04 20:39:23 +00:00

1"""Convert (Finnish: muuntaa) CVRF v1.2 XML to CSAF v2.0 JSON documents.""" 

2 

3import datetime as dti 

4import logging 

5import os 

6import pathlib 

7from typing import Union, no_type_check 

8 

9# [[[fill git_describe()]]] 

10__version__ = '2024.1.9+parent.abadcafe' 

11# [[[end]]] 

12__version_info__ = tuple( 

13 e if '-' not in e else e.split('-')[0] for part in __version__.split('+') for e in part.split('.') if e != 'parent' 

14) 

15 

16APP_ALIAS = str(pathlib.Path(__file__).parent.name) 

17APP_ENV = APP_ALIAS.upper() 

18APP_NAME = locals()['__doc__'] 

19DEBUG = bool(os.getenv(f'{APP_ENV}_DEBUG', '')) 

20ENCODING = 'utf-8' 

21ENCODING_ERRORS_POLICY = 'ignore' 

22DEFAULT_CONFIG_NAME = f'.{APP_ALIAS}.yml' 

23log = logging.getLogger() # Module level logger is sufficient 

24LOG_FOLDER = pathlib.Path('logs') 

25LOG_FILE = f'{APP_ALIAS}.log' 

26LOG_PATH = pathlib.Path(LOG_FOLDER, LOG_FILE) if LOG_FOLDER.is_dir() else pathlib.Path(LOG_FILE) 

27LOG_LEVEL = logging.INFO 

28VERSION = __version__ 

29VERSION_DOTTED_TRIPLE = '.'.join(__version_info__[:3]) 

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

31BOOLEAN_KEYS = ('force', 'fix_insert_current_version_into_revision_history') 

32INPUT_FILE_KEY = 'input_file' 

33NOW_CODE = 'now' 

34OVERWRITABLE_KEYS = [ 

35 'fix_insert_current_version_into_revision_history', 

36 'force_insert_default_reference_category', 

37 'remove_CVSS_values_without_vector', 

38 'force', 

39] 

40CSAF_FILE_SUFFIX = '.json' 

41 

42ConfigType = dict[str, Union[None, bool, int, float, str]] 

43LogLevel = int 

44Pathlike = Union[pathlib.Path, str] 

45ScopedMessage = tuple[LogLevel, str] 

46ScopedMessages = list[ScopedMessage] 

47WriterOptions = Union[None, dict[str, Union[bool, int]]] 

48 

49__all__: list[str] = [ 

50 'APP_ALIAS', 

51 'APP_ENV', 

52 'APP_NAME', 

53 'BOOLEAN_KEYS', 

54 'CSAF_FILE_SUFFIX', 

55 'DEBUG', 

56 'DEFAULT_CONFIG_NAME', 

57 'ConfigType', 

58 'ENCODING', 

59 'ENCODING_ERRORS_POLICY', 

60 'INPUT_FILE_KEY', 

61 'LogLevel', 

62 'NOW_CODE', 

63 'OVERWRITABLE_KEYS', 

64 'Pathlike', 

65 'ScopedMessage', 

66 'ScopedMessages', 

67 'VERSION', 

68 'VERSION_DOTTED_TRIPLE', 

69 'WriterOptions', 

70 'log', 

71] 

72 

73 

74@no_type_check 

75def formatTime_RFC3339(self, record, datefmt=None): # noqa 

76 """HACK A DID ACK we could inject .astimezone() to localize ...""" 

77 return dti.datetime.fromtimestamp(record.created, dti.timezone.utc).isoformat() # pragma: no cover 

78 

79 

80@no_type_check 

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

82 """Initialize module level logger""" 

83 global log # pylint: disable=global-statement 

84 

85 log_format = { 

86 'format': '%(asctime)s %(levelname)s [%(name)s]: %(message)s', 

87 'datefmt': TS_FORMAT_LOG, 

88 # 'filename': LOG_PATH, 

89 'level': LOG_LEVEL if level is None else level, 

90 } 

91 logging.Formatter.formatTime = formatTime_RFC3339 

92 logging.basicConfig(**log_format) 

93 log = logging.getLogger(APP_ENV if name is None else name) 

94 log.propagate = True 

95 

96 

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