nuclear 2.2.2__tar.gz → 2.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nuclear-2.2.2 → nuclear-2.2.3}/PKG-INFO +1 -1
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/logging.py +33 -19
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/collections.py +5 -1
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/time.py +5 -0
- nuclear-2.2.3/nuclear/version.py +1 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/PKG-INFO +1 -1
- nuclear-2.2.2/nuclear/version.py +0 -1
- {nuclear-2.2.2 → nuclear-2.2.3}/LICENSE +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/README.md +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/args/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/args/args_que.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/args/container.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/autocomplete/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/autocomplete/autocomplete.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/autocomplete/install.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/builder.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/decorator_builder.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/rule.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/rule_factory.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/typedef.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/completers/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/completers/file.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/help.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/context.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/error.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/inject.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/internal_vars.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/keyword.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/matcher.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/parser.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/transform.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/validate.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/value.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/types/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/types/boolean.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/types/filesystem.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/types/time.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/inspection/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/inspection/inspection.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/py.typed +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/shell/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/shell/background_cmd.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/shell/shell_utils.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/catch.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/context_error.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/exception.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/__init__.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/config.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/datamodel.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/env.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/files.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/functools.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/input.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/regex.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/strings.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/url.py +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/SOURCES.txt +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/dependency_links.txt +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/requires.txt +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/top_level.txt +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/setup.cfg +0 -0
- {nuclear-2.2.2 → nuclear-2.2.3}/setup.py +0 -0
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
from contextlib import contextmanager
|
|
2
2
|
from datetime import datetime, timezone
|
|
3
3
|
import logging
|
|
4
|
+
import json
|
|
4
5
|
import os
|
|
5
6
|
import sys
|
|
6
7
|
import threading
|
|
7
|
-
|
|
8
|
-
import
|
|
8
|
+
import time
|
|
9
|
+
from typing import Dict, Any, Callable, List, Optional
|
|
9
10
|
|
|
10
11
|
from colorama import init, Fore, Style
|
|
11
12
|
|
|
12
13
|
from nuclear.sublog.context_error import ContextError
|
|
13
14
|
from nuclear.sublog.exception import extended_exception_details
|
|
15
|
+
from nuclear.utils.collections import filter_not_none
|
|
14
16
|
from nuclear.utils.env import is_env_flag_enabled
|
|
15
17
|
from nuclear.utils.strings import strip_ansi_colors
|
|
16
18
|
|
|
17
19
|
LOG_FORMAT = f'{Style.DIM}[%(asctime)s]{Style.RESET_ALL} %(levelname)s %(message)s'
|
|
18
20
|
LOG_DATE_FORMAT = r'%Y-%m-%d %H:%M:%S'
|
|
21
|
+
LOG_DATE_FORMAT_UTC = r'%Y-%m-%d %H:%M:%SZ'
|
|
19
22
|
ISO_DATE_FORMAT = r'%Y-%m-%dT%H:%M:%S.%fZ'
|
|
20
23
|
LOGGING_LOGGER_NAME = 'nuclear.sublog'
|
|
21
|
-
STRUCTURED_LOGGING = is_env_flag_enabled('STRUCTURED_LOGGING', 'false')
|
|
22
24
|
|
|
23
|
-
log_level: str = os.environ.get('
|
|
25
|
+
log_level: str = os.environ.get('NUCLEAR_LOG_LEVEL', 'debug')
|
|
26
|
+
log_level_show: bool = is_env_flag_enabled('NUCLEAR_LOG_LEVEL_SHOW', 'true')
|
|
27
|
+
log_time_show: bool = is_env_flag_enabled('NUCLEAR_LOG_TIME', 'true')
|
|
24
28
|
simultaneous_print_lock = threading.Lock()
|
|
25
29
|
_logging_logger: logging.Logger = logging.getLogger(LOGGING_LOGGER_NAME)
|
|
26
|
-
_log_state = {
|
|
27
|
-
|
|
28
|
-
}
|
|
30
|
+
_log_state = {'init': False}
|
|
31
|
+
|
|
29
32
|
|
|
30
33
|
def init_logs():
|
|
31
34
|
"""Configure loggers: formatters, handlers and log levels"""
|
|
@@ -37,15 +40,15 @@ def init_logs():
|
|
|
37
40
|
}
|
|
38
41
|
if sys.version_info[1] >= 8:
|
|
39
42
|
logging_kwargs['force'] = True
|
|
40
|
-
if
|
|
43
|
+
if is_env_flag_enabled('NUCLEAR_STRUCTURED_LOGGING', 'false'):
|
|
44
|
+
logging_kwargs['datefmt'] = ISO_DATE_FORMAT
|
|
41
45
|
logging.basicConfig(**logging_kwargs)
|
|
42
46
|
for handler in logging.getLogger().handlers:
|
|
43
|
-
handler.setFormatter(
|
|
47
|
+
handler.setFormatter(StructuredFormatter())
|
|
44
48
|
else:
|
|
45
|
-
logging_kwargs['datefmt'] = ISO_DATE_FORMAT
|
|
46
49
|
logging.basicConfig(**logging_kwargs)
|
|
47
50
|
for handler in logging.getLogger().handlers:
|
|
48
|
-
handler.setFormatter(
|
|
51
|
+
handler.setFormatter(ColoredFormatter())
|
|
49
52
|
|
|
50
53
|
level = _get_logging_level(log_level)
|
|
51
54
|
root_logger = logging.getLogger(LOGGING_LOGGER_NAME)
|
|
@@ -65,7 +68,7 @@ def get_logger(logger_name: str) -> logging.Logger:
|
|
|
65
68
|
class ContextLogger:
|
|
66
69
|
def __init__(self, ctx: Dict[str, Any]):
|
|
67
70
|
self.ctx: Dict[str, Any] = ctx
|
|
68
|
-
self.structured_logging: bool =
|
|
71
|
+
self.structured_logging: bool = is_env_flag_enabled('NUCLEAR_STRUCTURED_LOGGING', 'false')
|
|
69
72
|
self.first_use = True
|
|
70
73
|
|
|
71
74
|
def error(self, message: str, **ctx):
|
|
@@ -147,9 +150,8 @@ def add_context(context_name: str, log: bool = False, **ctx):
|
|
|
147
150
|
|
|
148
151
|
|
|
149
152
|
class ColoredFormatter(logging.Formatter):
|
|
150
|
-
def __init__(self
|
|
153
|
+
def __init__(self):
|
|
151
154
|
logging.Formatter.__init__(self)
|
|
152
|
-
self.plain_formatter = plain_formatter
|
|
153
155
|
|
|
154
156
|
log_level_templates = {
|
|
155
157
|
'CRITICAL': f'{Style.BRIGHT + Fore.RED}CRIT {Style.RESET_ALL}',
|
|
@@ -160,18 +162,30 @@ class ColoredFormatter(logging.Formatter):
|
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
def format(self, record: logging.LogRecord) -> str:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
part_levelname = self.log_level_templates.get(record.levelname, record.levelname) if log_level_show else None
|
|
166
|
+
part_message = record.msg
|
|
167
|
+
part_time = self.format_time()
|
|
168
|
+
parts: List[str] = filter_not_none([part_time, part_levelname, part_message])
|
|
169
|
+
line = ' '.join(parts)
|
|
166
170
|
if not sys.stdout.isatty():
|
|
167
171
|
line = strip_ansi_colors(line)
|
|
168
172
|
return line
|
|
173
|
+
|
|
174
|
+
@staticmethod
|
|
175
|
+
def format_time() -> Optional[str]:
|
|
176
|
+
if not log_time_show:
|
|
177
|
+
return None
|
|
178
|
+
now_tz = datetime.now().astimezone()
|
|
179
|
+
if time.timezone == 0:
|
|
180
|
+
time_formatted = now_tz.strftime(LOG_DATE_FORMAT_UTC)
|
|
181
|
+
else:
|
|
182
|
+
time_formatted = now_tz.strftime(LOG_DATE_FORMAT)
|
|
183
|
+
return f'{Style.DIM}[{time_formatted}]{Style.RESET_ALL}'
|
|
169
184
|
|
|
170
185
|
|
|
171
186
|
class StructuredFormatter(logging.Formatter):
|
|
172
|
-
def __init__(self
|
|
187
|
+
def __init__(self):
|
|
173
188
|
logging.Formatter.__init__(self)
|
|
174
|
-
self.plain_formatter = plain_formatter
|
|
175
189
|
|
|
176
190
|
def format(self, record: logging.LogRecord) -> str:
|
|
177
191
|
timestamp: float = record.created
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, Callable, Iterable, TypeVar, List, Union
|
|
1
|
+
from typing import Any, Callable, Iterable, TypeVar, List, Union, Optional
|
|
2
2
|
|
|
3
3
|
T = TypeVar('T')
|
|
4
4
|
|
|
@@ -42,3 +42,7 @@ def flatten(collection: Iterable[Union[T, List[T]]]) -> List[T]:
|
|
|
42
42
|
else:
|
|
43
43
|
flat.append(item)
|
|
44
44
|
return flat
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def filter_not_none(items: List[Optional[T]]) -> List[T]:
|
|
48
|
+
return [item for item in items if item is not None]
|
|
@@ -14,6 +14,11 @@ def now() -> datetime:
|
|
|
14
14
|
return datetime.now(timezone.utc)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def now_tz() -> datetime:
|
|
18
|
+
"""Return current datetime with local timezone set"""
|
|
19
|
+
return datetime.now().astimezone()
|
|
20
|
+
|
|
21
|
+
|
|
17
22
|
def now_timestamp() -> int:
|
|
18
23
|
return datetime_to_timestamp(now())
|
|
19
24
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.2.3"
|
nuclear-2.2.2/nuclear/version.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.2.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|