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.
Files changed (67) hide show
  1. {nuclear-2.2.2 → nuclear-2.2.3}/PKG-INFO +1 -1
  2. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/logging.py +33 -19
  3. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/collections.py +5 -1
  4. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/time.py +5 -0
  5. nuclear-2.2.3/nuclear/version.py +1 -0
  6. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/PKG-INFO +1 -1
  7. nuclear-2.2.2/nuclear/version.py +0 -1
  8. {nuclear-2.2.2 → nuclear-2.2.3}/LICENSE +0 -0
  9. {nuclear-2.2.2 → nuclear-2.2.3}/README.md +0 -0
  10. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/__init__.py +0 -0
  11. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/__init__.py +0 -0
  12. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/args/__init__.py +0 -0
  13. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/args/args_que.py +0 -0
  14. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/args/container.py +0 -0
  15. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/autocomplete/__init__.py +0 -0
  16. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/autocomplete/autocomplete.py +0 -0
  17. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/autocomplete/install.py +0 -0
  18. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/__init__.py +0 -0
  19. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/builder.py +0 -0
  20. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/decorator_builder.py +0 -0
  21. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/rule.py +0 -0
  22. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/rule_factory.py +0 -0
  23. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/builder/typedef.py +0 -0
  24. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/completers/__init__.py +0 -0
  25. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/completers/file.py +0 -0
  26. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/help.py +0 -0
  27. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/__init__.py +0 -0
  28. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/context.py +0 -0
  29. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/error.py +0 -0
  30. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/inject.py +0 -0
  31. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/internal_vars.py +0 -0
  32. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/keyword.py +0 -0
  33. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/matcher.py +0 -0
  34. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/parser.py +0 -0
  35. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/transform.py +0 -0
  36. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/validate.py +0 -0
  37. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/parser/value.py +0 -0
  38. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/types/__init__.py +0 -0
  39. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/types/boolean.py +0 -0
  40. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/types/filesystem.py +0 -0
  41. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/cli/types/time.py +0 -0
  42. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/inspection/__init__.py +0 -0
  43. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/inspection/inspection.py +0 -0
  44. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/py.typed +0 -0
  45. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/shell/__init__.py +0 -0
  46. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/shell/background_cmd.py +0 -0
  47. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/shell/shell_utils.py +0 -0
  48. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/__init__.py +0 -0
  49. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/catch.py +0 -0
  50. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/context_error.py +0 -0
  51. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/sublog/exception.py +0 -0
  52. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/__init__.py +0 -0
  53. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/config.py +0 -0
  54. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/datamodel.py +0 -0
  55. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/env.py +0 -0
  56. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/files.py +0 -0
  57. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/functools.py +0 -0
  58. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/input.py +0 -0
  59. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/regex.py +0 -0
  60. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/strings.py +0 -0
  61. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear/utils/url.py +0 -0
  62. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/SOURCES.txt +0 -0
  63. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/dependency_links.txt +0 -0
  64. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/requires.txt +0 -0
  65. {nuclear-2.2.2 → nuclear-2.2.3}/nuclear.egg-info/top_level.txt +0 -0
  66. {nuclear-2.2.2 → nuclear-2.2.3}/setup.cfg +0 -0
  67. {nuclear-2.2.2 → nuclear-2.2.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nuclear
3
- Version: 2.2.2
3
+ Version: 2.2.3
4
4
  Summary: Declarative parser for command line interfaces
5
5
  Home-page: https://github.com/igrek51/nuclear
6
6
  Author: igrek51
@@ -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
- from typing import Dict, Any, Callable
8
- import json
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('LOG_LEVEL', 'debug')
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
- 'init': False,
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 not is_env_flag_enabled('STRUCTURED_LOGGING', 'false'):
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(ColoredFormatter(handler.formatter))
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(StructuredFormatter(handler.formatter))
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 = STRUCTURED_LOGGING
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, plain_formatter):
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
- if record.levelname in self.log_level_templates:
164
- record.levelname = self.log_level_templates[record.levelname].format(record.levelname)
165
- line: str = self.plain_formatter.format(record)
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, plain_formatter):
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"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nuclear
3
- Version: 2.2.2
3
+ Version: 2.2.3
4
4
  Summary: Declarative parser for command line interfaces
5
5
  Home-page: https://github.com/igrek51/nuclear
6
6
  Author: igrek51
@@ -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