out 0.79__py3-none-any.whl

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.
@@ -0,0 +1,544 @@
1
+ Metadata-Version: 2.1
2
+ Name: out
3
+ Version: 0.79
4
+ Summary: Fun take on logging for non-huge projects. Gets "outta" the way.
5
+ Home-page: https://github.com/mixmastamyk/out
6
+ Author: Mike Miller
7
+ Author-email: mixmastamyk@github.com
8
+ License: LGPL 3
9
+ Keywords: log logging events levels color terminal console standard out err
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/x-rst
20
+ License-File: LICENSE
21
+ Requires-Dist: console >0.9902
22
+ Requires-Dist: colorama ; os_name == "nt" and platform_version < "10.0.10586"
23
+ Provides-Extra: highlight
24
+ Requires-Dist: pygments >=2.4.0 ; extra == 'highlight'
25
+
26
+
27
+ Out
28
+ ===========
29
+
30
+ Fun take on logging for non-huge projects—out gets "outta" the way!
31
+
32
+ Background
33
+ --------------------------
34
+
35
+ If you're here it's very likely you already know that the Python standard
36
+ logging module is extremely flexible,
37
+ and that's great.
38
+ Unfortunately, it is overkill for small to medium projects,
39
+ and these days many larger ones too.
40
+ Additionally,
41
+ its various Java-isms grate on the nerves,
42
+ accentuating a big enterprisey design.
43
+
44
+ Meanwhile,
45
+ the rise of
46
+ `12 Factor App <https://12factor.net/logs>`_
47
+ patterns for daemons and services
48
+ means that simply logging to stdout/err is expected and desired
49
+ for portability:
50
+
51
+ *A twelve-factor app never concerns itself with routing or storage of its
52
+ output stream. It should not attempt to write to or manage logfiles.
53
+ Instead, each running process writes its event stream, unbuffered, to
54
+ stdout. During local development, the developer will view this stream in
55
+ the foreground of their terminal to observe the app’s behavior.*
56
+
57
+
58
+ Therefore,
59
+ for many (if not most) applications,
60
+ all the complexity and mumbo-jumbo in the logging package documentation about
61
+ multiple loggers with different levels, different handlers, formatters,
62
+ adapters, filters, rotation,
63
+ and complex configuration is flexibility at the *wrong level!*
64
+  In fairness,
65
+ this may not have always been the case,
66
+ and can still be helpful, perhaps on Windows.
67
+
68
+ Additionally, logging tools have also become standardized over time,
69
+ handling cross-language and cross-platform messages.
70
+ Imagine a pipeline where log events are routed and multiple tools can be
71
+ plugged in or out as needed—\
72
+ organization-wide rather than app- or language-wide.
73
+
74
+ So, unless you have unique requirements,
75
+ there's no need to reimplement ``logrotate``, ``syslog``, ``systemd``, and
76
+ proprietary metrics tools in every programming language.
77
+ Just blast those logs to stdout/stderr and get logging *outta* the way!
78
+
79
+ Enter the ``out`` project.
80
+ It's ready to start logging from the get go.
81
+ It uses Python's standard logging infrastructure by default,
82
+ so is still quite flexible when need be.
83
+
84
+ Well, you've heard this before.
85
+ However, *out* tries a bit harder create a fun, easy-to-use interface,
86
+ as discussed above.
87
+
88
+ **Naming**
89
+
90
+ Regarding the name,
91
+ well of course would have liked something along the lines of ``log`` but all
92
+ variations of that are *long gone* on PyPI.
93
+ ``out()`` is a name I've often used over the years as a poor-man's logger—\
94
+ really a functional wrapper around ``print``,
95
+ until I could get around to adding proper logging.
96
+ Now, the tradition continues.
97
+ The name is short, simple, and conceptually fits,
98
+ if a little bland.
99
+
100
+ Features
101
+ ------------
102
+
103
+ First of all,
104
+ out is concise as hell,
105
+ basically a singleton logger configuration ready on import.
106
+ In interactive mode:
107
+
108
+ .. code-block:: python-console
109
+
110
+ >>> import out
111
+
112
+ >>> out('And away we go…') # configurable default level
113
+ 🅸 main/func:1 And away we go…
114
+
115
+ >>> out.warn('Danger Will Robinson!')
116
+ 🆆 main/func:1 Danger Will Robinson!
117
+
118
+ (Imagine with nice ANSI colors. 😁)
119
+ Out has simple themes for message formats, styles, and icons.
120
+ Not to worry,
121
+ out is more conservative in "production mode,"
122
+ which may be turned on automatically by redirecting ``stderr``:
123
+
124
+ .. code-block:: shell
125
+
126
+ ⏵ python3 script.py |& cat # bash, for fish use: &|
127
+ 2018-09-10 17:18:19.123 ✗ ERROR main/func:1 Kerblooey!
128
+
129
+
130
+ .. note::
131
+
132
+ This is a library to simplify logging configuration for *applications.*
133
+
134
+ Libraries and independent modules should continue on logging *messages* as
135
+ they always have:
136
+
137
+ .. code-block:: python
138
+
139
+ import logging
140
+
141
+ log = logging.getLogger(__name__)
142
+
143
+ # do not configure loggers, just use:
144
+ log.debug('foo')
145
+
146
+
147
+ Colors, Highlighting, Unicode Icons
148
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
149
+
150
+ - Colors are ready to go in interactive mode,
151
+ and turn off automatically when output is redirected.
152
+
153
+ - Unicode symbols are used throughout as "icons" for increased readability and
154
+ conciseness.
155
+
156
+ - Syntax highlighting of data structures (oft parsed from remote APIs) is
157
+ available too, via Pygments.
158
+
159
+
160
+ Useful defaults, and easy to configure!
161
+
162
+ .. code-block:: python-console
163
+
164
+ >>> out.configure(
165
+ level='note', # level messages passed: str/int
166
+ default_level='info', # when called w/o a method: out('…')
167
+ datefmt='…', # see strftime
168
+ msgfmt='…', # see logging and below
169
+ stream=file, # stderr is default
170
+
171
+ theme=name|dict, # see below
172
+ icons=name|dict, # about themes
173
+ style=name|dict,
174
+ highlight=False, # disable highlighting
175
+ lexer='python3', # choose lexer
176
+ )
177
+
178
+ We'll go into more detail below.
179
+
180
+
181
+ Log Message Format
182
+ ~~~~~~~~~~~~~~~~~~~
183
+
184
+ By default out supports the curly-brace ``{}`` formatting style for both the
185
+ log message format and message template,
186
+ as it is a bit easier to read than printf-style.
187
+ Field definitions are found in the Python
188
+ `logging docs <https://docs.python.org/3/library/logging.html#logrecord-attributes>`_::
189
+
190
+ {asctime} Textual time when the LogRecord created.
191
+ {msecs} Millisecond portion of the creation time
192
+ {filename} Filename portion of pathname
193
+ {funcName} Function name
194
+ {lineno) Source line number where called.
195
+ {levelno} Numeric logging level for the message
196
+ {levelname} Text logging level for the message
197
+ {pathname} Full path of the source file called.
198
+ {message} The result of record.getMessage().
199
+ {module} Module (name portion of filename)
200
+ {name} Name of the logger (logging channel)
201
+
202
+ Use of the
203
+ ``out.format.ColorFormatter`` class adds these additional fields::
204
+
205
+ {on}{icon}{off} Per-level style and icon support.
206
+
207
+ For example:
208
+
209
+ .. code-block:: python
210
+
211
+ out.configure(
212
+ msgfmt='{on}{icon}{levelname:<7}{off} {message}',
213
+ )
214
+
215
+
216
+ DateTime Format
217
+ ++++++++++++++++++
218
+
219
+ These are configuable via the standard
220
+ `strftime <https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior>`_
221
+ syntax and the
222
+ ``datefmt`` keyword to ``configure``.
223
+
224
+ .. code-block:: python
225
+
226
+ out.configure(
227
+ datefmt='%y-%m-%d %H:%M:%S',
228
+ )
229
+
230
+
231
+ Message:
232
+ ++++++++++++++++++
233
+
234
+ When writing messages, printf ``%`` formatting style is supported as well
235
+ due to compatibility requirements with a majority of libraries:
236
+
237
+ .. code-block:: python
238
+
239
+ out.warn('foo: %s', bar)
240
+ out.warn('foo: {}', bar)
241
+
242
+ The second form may be used also,
243
+ though it will be a tiny bit slower,
244
+ since the printf-style must be tried first.
245
+
246
+ You'll want to use one of these forms,
247
+ as (in logging) they skip formatting of the string when the message isn't
248
+ sent.
249
+
250
+
251
+ Levels++
252
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
253
+
254
+ While the
255
+ `standard levels <https://docs.python.org/3/library/logging.html#levels>`_
256
+ continue to exist
257
+ (``NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL``).
258
+ A few additions and slight modifications have been made.
259
+ Commonly requested:
260
+
261
+ - ``TRACE``, for absurdly voluminous data, perhaps system calls or network
262
+ traffic.
263
+
264
+ - ``NOTE``, for **positive** messages
265
+ that should/must be shown by default---\
266
+ unlike the standard warning,
267
+ which could encourage the viewer to worry. e.g.:
268
+
269
+ | ``NOTE`` - Token is ABCXYZ, rather than…
270
+ | ``WARNING`` - Token is ABCXYZ.
271
+
272
+ - ``EXCEPT``, to differentiate common from unexpected errors.
273
+ Think ``FileNotFound`` vs. ``Exception``.
274
+
275
+ - ``FATAL``, an alias of ``CRITICAL``,
276
+ since that name is long, pushes alignment,
277
+ and does not capture intent as well as fatal.
278
+ Std-lib already allows this but still labels it critical on output.
279
+ Out does not.
280
+
281
+
282
+ Themes
283
+ ~~~~~~~~~~~~~~~~~~
284
+
285
+
286
+ Icons and Styles
287
+ +++++++++++++++++
288
+
289
+ ``out`` can be themed with icon sets and/or styles and are simply dictionaries
290
+ with one entry per level.
291
+
292
+
293
+ .. code-block:: python-console
294
+
295
+ >>> from out.themes import themes, icons, styles
296
+
297
+ >>> icons['circled'] # Unicode
298
+ {'TRACE': '🅣', 'DEBUG': '🅓', 'INFO': '🅘', 'WARNING': '🅦',
299
+ 'NOTE': '🅝', 'ERROR': '🅔', 'EXCEPT': '🅧', 'CRITICAL': '🅕',
300
+ 'FATAL': '🅕', 'NOTSET': '🅝'}
301
+
302
+ >>> styles['blink'] # ANSI escapes
303
+ {'TRACE': '\x1b[35m', 'DEBUG': '\x1b[34m', 'INFO': '\x1b[32m',
304
+ 'WARNING': '\x1b[93m', 'NOTE': '\x1b[96m', 'ERROR': '\x1b[31m',
305
+ 'EXCEPT': '\x1b[91m', 'CRITICAL': '\x1b[97m',
306
+ 'FATAL': '\x1b[97;5m', 'NOTSET': '\x1b[0m'}
307
+
308
+ The
309
+ `console <https://mixmastamyk.bitbucket.io/console/>`_
310
+ package is a good choice to generate ANSI styles for the levels,
311
+ as well as styling other fields:
312
+
313
+ .. code-block:: python
314
+
315
+ from console import fg, bg, fx
316
+ import out
317
+
318
+ blue_note = dict(
319
+ NOTE=str(fg.lightblue + fx.bold + fx.reverse),
320
+ # other levels…
321
+ )
322
+ out.configure(
323
+ style=blue_note, # ← level styles, ↓ field styles
324
+ msgfmt=bg.blue('{asctime}') + ' {message}',
325
+ )
326
+ out.note('John Coltrane')
327
+
328
+
329
+ Creating and Using Themes
330
+ ++++++++++++++++++++++++++
331
+
332
+ A full theme is the whole kit together in a mapping—\
333
+ styles, icons, ``message`` and/or ``datefmt`` templates:
334
+
335
+ .. code-block:: python-console
336
+
337
+ >>> interactive_theme = {
338
+ 'style': {}, # level:value mapping, see above
339
+ 'icons': {}, # level:value
340
+ 'fmt': '{asctime} {icon} {message}', # message format
341
+ 'datefmt': '%H:%M:%S', # date/time format,
342
+ }
343
+
344
+
345
+ In the ``configure`` method of the out logger,
346
+ to use a theme from the themes module,
347
+ simply specify an existing one by name:
348
+
349
+ .. code-block:: python-console
350
+
351
+ >>> out.configure(
352
+ theme='production',
353
+ )
354
+
355
+ Or by setting a custom mapping, as created above:
356
+
357
+ .. code-block:: python-console
358
+
359
+ >>> out.configure(
360
+ theme=interactive_theme, # or perhaps just icons:
361
+ icons=dict(DEBUG='• ', INFO='✓ ', WARNING='⚠ ', ) # …
362
+ )
363
+
364
+ A few themes are bundled:
365
+
366
+ Icons:
367
+ ascii,
368
+ ascii_symbol,
369
+ circled,
370
+ circled_lower,
371
+ rounded,
372
+ symbol
373
+
374
+ Styles:
375
+ - norm
376
+ - bold
377
+ - mono (monochrome)
378
+ - blink (fatal error only)
379
+
380
+ Full themes:
381
+ - interactive
382
+ - production
383
+ - plain (Uses logging.Formatter for lower overhead.)
384
+ - json (Uses formatter.JSONFormatter)
385
+ - mono (monochrome)
386
+ - linux_interactive, linux_production (vga console)
387
+
388
+
389
+ .. note::
390
+
391
+ When there are conflicting arguments to the ``configure`` method,
392
+ the last specified will win.
393
+ This requires a Python version >=3.6, due to ordered keyword args.
394
+ Below this version it is not recommended to try since keyword order
395
+ will be undefined and therefore the result.
396
+ One workaround, call ``configure()`` twice.
397
+
398
+
399
+ Syntax Highlighting w/Pygments
400
+ --------------------------------
401
+
402
+ When Pygments is installed,
403
+ syntax highlighting is available for Python data structures and code,
404
+ as well as JSON and XML strings—\
405
+ potentially anything Pygments can highlight.
406
+ This can be helpful when debugging remote APIs for example.
407
+
408
+ A lexer may be
409
+ `selected by name <http://pygments.org/docs/lexers/>`_
410
+ via ``configure(lexer=LEXER_NAME)``,
411
+ disabled by setting to ``None``.
412
+ Some common lexer names are: ``('json', 'python3', 'xml')``.
413
+
414
+ **Use:**
415
+
416
+ Message text following a ``{, [, <, or '`` char
417
+ is highlighted with the current
418
+ lexer+formatter:
419
+
420
+ .. code-block:: python
421
+
422
+ out.configure(level='trace')
423
+
424
+ # default Python3
425
+ out.trace('PYON data: %s',
426
+ {'data': [None, True, False, 123]})
427
+
428
+ out.configure(lexer='json')
429
+ out.trace('JSON data: '
430
+ '{"data": [null, true, false, 123]}')
431
+
432
+ (Imagine with lovely ANSI flavors. 😁)
433
+
434
+
435
+ Tips
436
+ ---------
437
+
438
+ - By default the logger prints to ``stderr``.
439
+ The reason being that when used in an interactive script normal application
440
+ output may be easily segregated from log messages during redirection.
441
+
442
+ .. code-block:: shell
443
+
444
+ # bash, fish
445
+ ⏵ script.py 2> logfile.txt
446
+
447
+ Configurable via the ``stream`` keyword to ``.configure()``:
448
+
449
+ .. code-block:: python
450
+
451
+ import sys, out
452
+
453
+ out.configure(
454
+ stream=sys.stdout,
455
+ )
456
+
457
+ - Upgrading a long script from ``print()`` is easy:
458
+
459
+ .. code-block:: python
460
+
461
+ import out
462
+
463
+ print = out # or other level: out.note
464
+
465
+ Or perhaps some logging was already added, but you'd like to downsize.
466
+ Add this to your main script::
467
+
468
+ import out as logger
469
+
470
+ Less code will need to be changed.
471
+
472
+ .. ~ - Want to keep your complex configuration but use the ``ColorFormatter`` class
473
+ .. ~ and themes in your own project?
474
+
475
+ - The ``ColorFormatter`` and ``JSONFormatter`` classes can be used in your own
476
+ project:
477
+
478
+ .. code-block:: python-console
479
+
480
+ >>> from out.format import ColorFormatter
481
+
482
+ >>> cf = ColorFormatter()
483
+ >>> handler.setFormatter(cf)
484
+
485
+ - To print the current logging configuration:
486
+
487
+ .. code-block:: python-console
488
+
489
+ >>> out.log_config() # quotes to shut off highlighting:
490
+ '''
491
+ 🅳 Logging config:
492
+ 🅳 / name: main, id: 139973461370360
493
+ 🅳 .level: trace (7)
494
+ 🅳 .default_level: info (20)
495
+ 🅳 + Handler: 0 <StreamHandler <stderr> (NOTSET)>
496
+ 🅳 + Formatter: <out.format.ColorFormatter object at 0x7f4e1c65efd0>
497
+ 🅳 .style: <logging.StrFormatStyle object at 0x7f4e1c65ef28>
498
+ 🅳 .datefmt: '%H:%M:%S'
499
+ 🅳 .msgfmt: ' {on}{icon}{off} {message}'
500
+ '''
501
+
502
+ The logger in the main script file is named "main,"
503
+ also known as the "root" logger.
504
+
505
+
506
+ Troubleshooting
507
+ -----------------
508
+
509
+ - If you'd like to know what ``out`` is doing,
510
+ try running the ``.log_config()`` method to log what's currently up:
511
+
512
+ .. code-block:: python-console
513
+
514
+ >>> out.log_config()
515
+
516
+ .. code-block:: shell
517
+
518
+ 🅳 out logging config, version: '0.70a1'
519
+ 🅳 .name: main, id: 0x7f88e9ec7198
520
+ 🅳 .level: debug (10)
521
+ 🅳 .default_level: info (20)
522
+ 🅳 + Handler: 0 <StreamHandler <stdout> (NOTSET)>
523
+ 🅳 + Formatter: <out.format.ColorFormatter object at 0x7f88e9ce1b70>
524
+ 🅳 .datefmt: '%H:%M:%S'
525
+ 🅳 .msgfmt: ' {on}{icon:<2}{off} \x1b[38;5;242m{name}/\x1b[38;5;245m{funcName}:\x1b[32m{lineno:<3}\x1b[0m {message}'
526
+ 🅳 fmt_style: <logging.StrFormatStyle object at 0x7f88e9ca5080>
527
+ 🅳 theme.styles: {'TRACE': '\x1b[35m', 'DEBUG': '\x1b[34m', 'INFO': '\x1b[32m', 'NOTE': '\x1b[96m', 'WARNING': '\x1b[93m', 'ERROR': '\x1b[31m', 'EXCEPT': '\x1b[91m', 'CRITICAL': '\x1b[97m', 'FATAL': '\x1b[97m', 'NOTSET': ''}
528
+ 🅳 theme.icons: {'TRACE': '🆃', 'DEBUG': '🅳', 'INFO': '🅸', 'NOTE': '🅽', 'WARNING': '🆆', 'ERROR': '🅴', 'EXCEPT': '🆇', 'CRITICAL': '🅵', 'FATAL': '🅵', 'NOTSET': '🅽'}
529
+ 🅳 highlighting: 'Python3Lexer', 'Terminal256Formatter'
530
+
531
+ Import ``out`` in debug mode first and you can see any logging other modules do
532
+ as the start up.
533
+
534
+ - If you're using fbterm, make sure the ``TERM`` environment variable is set
535
+ to ``fbterm``.
536
+ This makes several adjustments to help it work better under that terminal.
537
+
538
+
539
+ Install
540
+ ------------
541
+
542
+ .. code-block:: shell
543
+
544
+ ⏵ pip3 install out # or out[highlight]
@@ -0,0 +1,12 @@
1
+ out/__init__.py,sha256=-XCC1Y_M_CSi38EmwAdQQvvXEvGHBOhPTnIIlVtyiqU,9162
2
+ out/demos.py,sha256=Py5apf8HVMXJGoCZ3m2VaEPIUqcn4F8jJ73WCd-iTQg,2065
3
+ out/detection.py,sha256=6k2gLEQgeXQ4a0nfgX6d_KksjeCklAyBcNP4s6n__2A,666
4
+ out/format.py,sha256=6ELMAcGf5wLpFPWI_Ti0zz6pi4R4SgEZWKtfsPYgZuY,9727
5
+ out/highlight.py,sha256=LNjOe-JYjepE6lPTy_zBVzWi3ZLqn9BT2ivcI7hu51E,3756
6
+ out/test_mod.py,sha256=GAJwqn_XFwUObcwIds--cKhzNQZyBwYfKl7z2F9D_v0,341
7
+ out/themes.py,sha256=A8njH6QkHORNoxCQhzgZfFP70bjrzfgcx5XIlSyPogM,8420
8
+ out-0.79.dist-info/LICENSE,sha256=2n6rt7r999OuXp8iOqW9we7ORaxWncIbOwN1ILRGR2g,7651
9
+ out-0.79.dist-info/METADATA,sha256=ANscLfozCm8xm4yJeiXFW7dFSIFlvKcNOYdqAaK4TgA,16268
10
+ out-0.79.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
11
+ out-0.79.dist-info/top_level.txt,sha256=VANKxcbp6pVzTsK3Kf1tYqv2SvNKn5zl1GbLeIGRpz0,4
12
+ out-0.79.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ out