cli2 6.0.0rc15__tar.gz → 6.0.0rc16__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 (46) hide show
  1. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/PKG-INFO +1 -1
  2. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/__init__.py +1 -2
  3. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/cli.py +1 -1
  4. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/configuration.py +1 -1
  5. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/display.py +2 -0
  6. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/log.py +158 -49
  7. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/proc.py +1 -1
  8. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/traceback.py +1 -3
  9. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2.egg-info/PKG-INFO +1 -1
  10. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/setup.py +1 -1
  11. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/MANIFEST.in +0 -0
  12. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/asyncio.py +0 -0
  13. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/cli2.py +0 -0
  14. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/colors.py +0 -0
  15. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/decorators.py +0 -0
  16. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/__init__.py +0 -0
  17. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/conf.py +0 -0
  18. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/example.py +0 -0
  19. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/example_obj.py +0 -0
  20. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/nesting.py +0 -0
  21. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/obj.py +0 -0
  22. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/obj2.py +0 -0
  23. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/test.py +0 -0
  24. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/examples/traceback_demo.py +0 -0
  25. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/exceptions.py +0 -0
  26. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/file.py +0 -0
  27. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/find.py +0 -0
  28. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/flow2.py +0 -0
  29. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/interactive.py +0 -0
  30. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/lock.py +0 -0
  31. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/mask.py +0 -0
  32. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/node.py +0 -0
  33. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/notlevenshtein.py +0 -0
  34. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/queue.py +0 -0
  35. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/sphinx.py +0 -0
  36. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/table.py +0 -0
  37. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/template2.py +0 -0
  38. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/test.py +0 -0
  39. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2/theme.py +0 -0
  40. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2.egg-info/SOURCES.txt +0 -0
  41. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2.egg-info/dependency_links.txt +0 -0
  42. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2.egg-info/entry_points.txt +0 -0
  43. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2.egg-info/requires.txt +0 -0
  44. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/cli2.egg-info/top_level.txt +0 -0
  45. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/pyproject.toml +0 -0
  46. {cli2-6.0.0rc15 → cli2-6.0.0rc16}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cli2
3
- Version: 6.0.0rc15
3
+ Version: 6.0.0rc16
4
4
  Home-page: https://yourlabs.io/oss/cli2
5
5
  Author: James Pic
6
6
  Author-email: jamespic@gmail.com
@@ -1,7 +1,6 @@
1
1
  # flake8: noqa
2
2
 
3
3
  from .configuration import Configuration, cfg
4
- cfg.defaults['CLI2_TRACEBACK_DISABLE'] = ''
5
4
 
6
5
  from .cli import (
7
6
  cmd,
@@ -46,7 +45,7 @@ from .table import Table
46
45
 
47
46
  import os
48
47
 
49
- if not bool(cfg['CLI2_TRACEBACK_DISABLE']):
48
+ if not bool(os.getenv('CLI2_TRACEBACK_DISABLE')):
50
49
  from .traceback import enable
51
50
  enable()
52
51
 
@@ -228,7 +228,7 @@ class Group(EntryPoint, dict):
228
228
  def group(self, name, grpclass=None, **kwargs):
229
229
  """Return a new sub-group."""
230
230
  kwargs.setdefault('cmdclass', self.cmdclass)
231
- grpclass = grpclass or Group
231
+ grpclass = grpclass or type(self)
232
232
  self[name] = grpclass(name, **kwargs)
233
233
  return self[name]
234
234
 
@@ -65,7 +65,7 @@ class Configuration(dict):
65
65
 
66
66
  cli = cli2.Group()
67
67
 
68
- cli2.cfg['API_URL'] = 'What is your API URL?'
68
+ cli2.cfg.questions['API_URL'] = 'What is your API URL?'
69
69
 
70
70
  @cli.cmd
71
71
  def foo():
@@ -22,6 +22,8 @@ _print = print
22
22
  def color_enabled():
23
23
  if 'FORCE_COLOR' in os.environ:
24
24
  return bool(os.getenv('FORCE_COLOR', ''))
25
+ elif 'NO_COLOR' in os.environ:
26
+ return not bool(os.getenv('NO_COLOR', ''))
25
27
  return sys.stdout.isatty()
26
28
 
27
29
 
@@ -20,6 +20,7 @@ In general, you'll want to use want to use:
20
20
  can recover from that (ie. retrying a connection)
21
21
  - ``log.error()``: your program couldn't perform some function
22
22
  - ``log.critical()``: your program may not be able to continue running
23
+ - ``log.exception()``: log the traceback
23
24
 
24
25
  Anyway, it's structlog so you can also create bound loggers that will carry on
25
26
  the given parameters:
@@ -63,14 +64,20 @@ import logging.config
63
64
  import os
64
65
  import re
65
66
  import sys
67
+ import io
66
68
  import structlog
69
+ import warnings
67
70
  import yaml
68
71
  from pathlib import Path
69
72
 
70
73
  from cli2.traceback import TracebackFormatter
74
+ from cli2.theme import theme
71
75
  import cli2.display
72
76
 
73
77
 
78
+ COLOR_ENABLED = cli2.display.color_enabled()
79
+
80
+
74
81
  class YAMLFormatter:
75
82
  def __init__(self, colors=True):
76
83
  self.colors = colors
@@ -79,7 +86,86 @@ class YAMLFormatter:
79
86
  value = cli2.display.yaml_dump(value)
80
87
  if self.colors:
81
88
  value = cli2.display.yaml_highlight(value)
82
- return '\n' + value
89
+ return '\n' + value.strip() + '\n'
90
+
91
+
92
+ _NOTHING = structlog.dev._NOTHING
93
+
94
+
95
+ class ConsoleRenderer(structlog.dev.ConsoleRenderer):
96
+ def __init__(self, *args, **kwargs):
97
+ if kwargs.get('colors', False):
98
+ kwargs['level_styles'] = dict(
99
+ debug=str(theme.gray),
100
+ info=str(theme.green),
101
+ warning=str(theme.orange),
102
+ error=str(theme.red),
103
+ critical=str(theme.pink),
104
+ exception=str(theme.mauve),
105
+ )
106
+
107
+ super().__init__(*args, **kwargs)
108
+ self._columns.append(
109
+ structlog.dev.Column(
110
+ 'json',
111
+ YAMLFormatter(colors=self.colors),
112
+ ),
113
+ )
114
+
115
+ def _configure_columns(self) -> None:
116
+ super()._configure_columns()
117
+ if self.colors:
118
+ self._default_column_formatter.key_style = str(theme.orange)
119
+ self._default_column_formatter.value_style = str(theme.green)
120
+
121
+ def __call__(self, logger, name, event_dict):
122
+ """ Override to display JSON column last """
123
+ stack = event_dict.pop("stack", None)
124
+ exc = event_dict.pop("exception", None)
125
+ exc_info = event_dict.pop("exc_info", None)
126
+
127
+ self.columns[3].formatter.width = 0
128
+ kvs = [
129
+ col.formatter(col.key, val)
130
+ for col in self.columns
131
+ if col.key != 'json'
132
+ and (val := event_dict.pop(col.key, _NOTHING)) is not _NOTHING
133
+ # added the following line:
134
+ ] + [
135
+ self._default_column_formatter(key, event_dict[key])
136
+ for key in (sorted(event_dict) if self._sort_keys else event_dict)
137
+ if key != 'json'
138
+ ] + [
139
+ # added all this list
140
+ col.formatter(col.key, val)
141
+ for col in self.columns
142
+ if col.key == 'json'
143
+ and (val := event_dict.pop(col.key, _NOTHING)) is not _NOTHING
144
+ ]
145
+
146
+ sio = io.StringIO()
147
+ sio.write((" ".join(kv for kv in kvs if kv)).rstrip(" "))
148
+
149
+ if stack is not None:
150
+ sio.write("\n" + stack)
151
+ if exc_info or exc is not None:
152
+ sio.write("\n\n" + "=" * 79 + "\n")
153
+
154
+ exc_info = structlog.processors._figure_out_exc_info(exc_info)
155
+ if exc_info:
156
+ self._exception_formatter(sio, exc_info)
157
+ elif exc is not None:
158
+ from structlog.dev import plain_traceback
159
+ if self._exception_formatter is not plain_traceback:
160
+ warnings.warn(
161
+ "Remove `format_exc_info` from your processor chain "
162
+ "if you want pretty exceptions.",
163
+ stacklevel=2,
164
+ )
165
+
166
+ sio.write("\n" + exc)
167
+
168
+ return sio.getvalue()
83
169
 
84
170
 
85
171
  def cli2_traceback(sio, exc_info):
@@ -95,7 +181,6 @@ def configure(log_file=None):
95
181
 
96
182
  :param log_file: override for :envvar:`LOG_FILE`.
97
183
  """
98
- from cli2.configuration import cfg
99
184
  LOG_LEVEL = os.getenv('LOG_LEVEL', 'WARNING').upper()
100
185
  if log_file is None:
101
186
  log_file = os.getenv('LOG_FILE', 'auto')
@@ -136,9 +221,56 @@ def configure(log_file=None):
136
221
  if log_file:
137
222
  handlers.append('file')
138
223
 
139
- kwargs = dict()
140
- if not bool(cfg['CLI2_TRACEBACK_DISABLE']):
141
- kwargs['exception_formatter'] = cli2_traceback
224
+ from structlog.processors import (
225
+ StackInfoRenderer,
226
+ TimeStamper,
227
+ add_log_level,
228
+ )
229
+ from structlog.contextvars import merge_contextvars
230
+ from structlog.dev import _has_colors, set_exc_info
231
+ colors = (
232
+ os.environ.get("NO_COLOR", "") == ""
233
+ and (
234
+ os.environ.get("FORCE_COLOR", "") != ""
235
+ or (
236
+ _has_colors
237
+ and sys.stdout is not None
238
+ and hasattr(sys.stdout, "isatty")
239
+ and sys.stdout.isatty()
240
+ )
241
+ )
242
+ )
243
+
244
+ def move_json_to_end(_, __, event_dict):
245
+ # Pull json out if present, then put it back at the very end
246
+ json_value = event_dict.pop("json", None)
247
+ if json_value is not None:
248
+ event_dict["json"] = json_value
249
+ return event_dict
250
+
251
+ def processors(disable_color=False):
252
+ kwargs = dict()
253
+ if not bool(os.getenv('CLI2_TRACEBACK_DISABLE')):
254
+ kwargs['exception_formatter'] = cli2_traceback
255
+
256
+ processors = [
257
+ structlog.stdlib.ProcessorFormatter.remove_processors_meta,
258
+ merge_contextvars,
259
+ add_log_level,
260
+ StackInfoRenderer(),
261
+ set_exc_info,
262
+ ]
263
+ if not os.getenv('NO_TIMESTAMPER'):
264
+ processors.append(
265
+ TimeStamper(fmt="%Y-%m-%d %H:%M:%S", utc=False),
266
+ )
267
+ processors.append(
268
+ ConsoleRenderer(
269
+ colors=colors and not disable_color,
270
+ **kwargs,
271
+ )
272
+ )
273
+ return processors
142
274
 
143
275
  LOGGING = {
144
276
  'version': 1,
@@ -147,52 +279,12 @@ def configure(log_file=None):
147
279
  'plain': {
148
280
  'foreign_pre_chain': pre_chain,
149
281
  '()': structlog.stdlib.ProcessorFormatter,
150
- 'processors': [
151
- structlog.stdlib.ProcessorFormatter.remove_processors_meta,
152
- structlog.dev.ConsoleRenderer(
153
- columns=[
154
- structlog.dev.Column(
155
- 'json',
156
- YAMLFormatter(colors=False),
157
- ),
158
- structlog.dev.Column(
159
- '',
160
- structlog.dev.KeyValueColumnFormatter(
161
- key_style="",
162
- value_style="",
163
- reset_style="",
164
- value_repr=str,
165
- ),
166
- )
167
- ],
168
- **kwargs,
169
- )
170
- ],
282
+ 'processors': processors(True),
171
283
  },
172
284
  'colored': {
173
285
  'foreign_pre_chain': pre_chain,
174
286
  '()': structlog.stdlib.ProcessorFormatter,
175
- 'processors': [
176
- structlog.stdlib.ProcessorFormatter.remove_processors_meta,
177
- structlog.dev.ConsoleRenderer(
178
- columns=[
179
- structlog.dev.Column(
180
- '',
181
- structlog.dev.KeyValueColumnFormatter(
182
- key_style=structlog.dev.CYAN,
183
- value_style=structlog.dev.MAGENTA,
184
- reset_style=structlog.dev.RESET_ALL,
185
- value_repr=str,
186
- ),
187
- ),
188
- structlog.dev.Column(
189
- 'json',
190
- YAMLFormatter(colors=True),
191
- ),
192
- ],
193
- **kwargs,
194
- )
195
- ]
287
+ 'processors': processors(),
196
288
  },
197
289
  },
198
290
  'handlers': {
@@ -234,8 +326,10 @@ def configure(log_file=None):
234
326
  structlog.stdlib.add_log_level,
235
327
  structlog.stdlib.PositionalArgumentsFormatter(),
236
328
  ]
329
+
237
330
  if 'NO_TIMESTAMPER' not in os.environ:
238
331
  processors.append(timestamper)
332
+
239
333
  processors += [
240
334
  structlog.processors.StackInfoRenderer(),
241
335
  structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
@@ -277,5 +371,20 @@ def parse(data):
277
371
  return entries
278
372
 
279
373
 
280
- configure()
281
- log = structlog.get_logger('cli2')
374
+ class LazyProxy:
375
+ def __init__(self):
376
+ self.obj = None
377
+
378
+ def __getattr__(self, key):
379
+ try:
380
+ return getattr(self.obj, key)
381
+ except AttributeError:
382
+ self.obj = self.obj_factory()
383
+ return getattr(self.obj, key)
384
+
385
+ def obj_factory(self):
386
+ configure()
387
+ return structlog.get_logger('cli2')
388
+
389
+
390
+ log = LazyProxy()
@@ -15,7 +15,7 @@ Example usage:
15
15
  proc = cli2.Proc('foo bar')
16
16
 
17
17
  # or as list, better when building commands
18
- proc = await cli2.Proc('foo', 'bar')
18
+ proc = cli2.Proc('foo', 'bar')
19
19
 
20
20
  # wait in async loop
21
21
  await proc.wait()
@@ -454,10 +454,8 @@ _formatter = TracebackFormatter()
454
454
  def enable():
455
455
  """Enable the custom traceback formatter."""
456
456
  # Defer import to avoid circularity
457
- from cli2.configuration import cfg
458
-
459
457
  # Check config if tracebacks should be enabled
460
- if not bool(cfg.get("CLI2_TRACEBACK_DISABLE")):
458
+ if not bool(os.getenv("CLI2_TRACEBACK_DISABLE")):
461
459
  _formatter.enable()
462
460
 
463
461
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cli2
3
- Version: 6.0.0rc15
3
+ Version: 6.0.0rc16
4
4
  Home-page: https://yourlabs.io/oss/cli2
5
5
  Author: James Pic
6
6
  Author-email: jamespic@gmail.com
@@ -44,7 +44,7 @@ from setuptools import setup
44
44
 
45
45
  setup(
46
46
  name='cli2',
47
- version='6.0.0rc15',
47
+ version='6.0.0rc16',
48
48
  setup_requires='setupmeta',
49
49
  packages=['cli2'],
50
50
  install_requires=[
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