Logging convenience routines.
*Latest release 20241109*:
* setup_logging: make it work with no arguments.
* ifdebug: handle loginfo.level=None.
The logging package is very useful, but a little painful to use.
This package provides low impact logging setup and some extremely
useful if unconventional context hooks for logging.
The default logging verbosity output format has different defaults
based on whether an output log file is a tty
and whether the environment variable `$DEBUG` is set, and to what.
On terminals warnings and errors get ANSI colouring.
A mode is available that uses `cs.upd` for certain log levels.
Log messages dispatched via `warning` and friends from this module
are automatically prefixed with the current `cs.pfx` prefix string,
providing automatic message context.
Some examples:
--------------
Program initialisation:
from cs.logutils import setup_logging
def main(argv):
cmd = os.path.basename(argv.pop(0))
setup_logging(cmd)
Basic logging from anywhere:
from cs.logutils import info, warning, error
[...]
def some_function(...):
[...]
error("nastiness found! bad value=%r", bad_value)
## <a name="add_logfile"></a>`add_logfile(filename, logger=None, mode='a', encoding=None, delay=False, format=None, no_prefix=False)`
Add a `FileHandler` logging to the specified `filename`;
return the chosen logger and the new handler.
Parameters:
* `logger`: if supplied and not `None`, add the `FileHandler` to that
`Logger`, otherwise to the root Logger. If `logger` is a string, call
`logging.getLogger(logger)` to obtain the logger.
* `mode`, `encoding` and `delay`: passed to the `FileHandler`
initialiser.
* `format`: used to override the handler's default format.
* `no_prefix`: if true, do not put the `Pfx` context onto the front of the message.
## <a name="critical"></a>`critical(msg, *args, **kwargs)`
Emit a log at `logging.CRITICAL` level with the current `Pfx` prefix.
## <a name="D"></a>`D(msg, *args)`
Print formatted debug string straight to `sys.stderr` if
`D_mode` is true, bypassing the logging modules entirely.
A quick'n'dirty debug tool.
## <a name="debug"></a>`debug(msg, *args, **kwargs)`
Emit a log at `logging.DEBUG` level with the current `Pfx` prefix.
## <a name="error"></a>`error(msg, *args, **kwargs)`
Emit a log at `logging.ERROR` level with the current `Pfx` prefix.
## <a name="exception"></a>`exception(msg, *args, **kwargs)`
Emit an exception log with the current `Pfx` prefix.
## <a name="ifdebug"></a>`ifdebug()`
Test the `loginfo.level` against `logging.DEBUG`.
## <a name="ifverbose"></a>`ifverbose(is_verbose, msg, *args, **kwargs)`
Conditionally log a message.
If `is_verbose` is `None`, log at `VERBOSE` level and rely on the logging setup.
Otherwise, if `is_verbose` is true, log at `INFO` level.
## <a name="infer_logging_level"></a>`infer_logging_level(env_debug=None, environ=None, verbose=None)`
Infer a logging level from the `env_debug`, which by default
comes from the environment variable `$DEBUG`.
Usually default to `logging.WARNING`, but if `sys.stderr` is a terminal,
default to `logging.INFO`.
Parse the environment variable `$DEBUG` as a comma separated
list of flags.
Examine the in sequence flags to affect the logging level:
* numeric < 1: `logging.WARNING`
* numeric >= 1 and < 2: `logging.INFO`
* numeric >= 2: `logging.DEBUG`
* `"DEBUG"`: `logging.DEBUG`
* `"STATUS"`: `STATUS`
* `"INFO"`: `logging.INFO`
* `"TRACK"`: `TRACK`
* `"WARNING"`: `logging.WARNING`
* `"ERROR"`: `logging.ERROR`
Return an object with the following attributes:
* `.level`: A logging level.
* `.flags`: All the words from `$DEBUG` as separated by commas and uppercased.
## <a name="info"></a>`info(msg, *args, **kwargs)`
Emit a log at `logging.INFO` level with the current `Pfx` prefix.
## <a name="log"></a>`log(level, msg, *args, **kwargs)`
Emit a log at the specified level with the current `Pfx` prefix.
## <a name="logException"></a>`logException(exc_type, exc_value, exc_tb)`
Replacement for `sys.excepthook` that reports via the `cs.logutils`
logging wrappers.
## <a name="LoggingState"></a>Class `LoggingState(types.SimpleNamespace)`
A logging setup arranged for conventional UNIX command line use.
*`LoggingState.__init__(self, cmd=None, main_log=None, format=None, level=None, flags=None, upd_mode=None, ansi_mode=None, trace_mode=None, verbose=None, supplant_root_logger=False)`*:
Prepare the `LoggingState` for conventional UNIX command
line error messaging.
Amongst other things, the default logger now includes
the `cs.pfx` prefix in the message.
This function runs in two modes:
- if logging has not been set up, it sets up a root logger
- if the root logger already has handlers,
monkey patch the first handler's formatter to prefix the `cs.pfx` state
Parameters:
* `cmd`: program name, default from `basename(sys.argv[0])`.
* `main_log`: default logging system.
If `None`, the main log will go to `sys.stderr`;
if `main_log` is a string, is it used as a filename to
open in append mode;
otherwise main_log should be a stream suitable
for use with `logging.StreamHandler()`.
The resulting log handler is added to the `logging` root logger.
* `format`: the message format for `main_log`.
If `None`, use `DEFAULT_PFX_FORMAT_TTY`
when `main_log` is a tty or FIFO,
otherwise `DEFAULT_PFX_FORMAT`.
* `level`: `main_log` logging level.
If `None`, infer a level from the environment
using `infer_logging_level()`.
* `flags`: a string containing debugging flags separated by commas.
If `None`, infer the flags from the environment using
`infer_logging_level()`.
The following flags have meaning:
`D`: set cs.logutils.D_mode to True;
`TDUMP`: attach a signal handler to SIGHUP to do a thread stack dump;
`TRACE`: enable various noisy tracing facilities;
`UPD`, `NOUPD`: set the default for `upd_mode` to True or False respectively.
* `upd_mode`: a Boolean to activate cs.upd as the `main_log` method;
if `None`, set it to `True` if `flags` contains 'UPD',
otherwise to `False` if `flags` contains 'NOUPD',
otherwise set it from `main_log.isatty()`.
A true value causes the root logger to use `cs.upd` for logging.
* `ansi_mode`: if `None`,
set it from `main_log.isatty() and not cs.colourise.env_no_color()`,
which thus honours the `$NO_COLOR` environment variable
(see https://no-color.org/ for the convention).
A true value causes the root logger to colour certain logging levels
using ANSI terminal sequences (currently only if `cs.upd` is used).
* `trace_mode`: if `None`, set it according to the presence of
'TRACE' in flags. Otherwise if `trace_mode` is true, set the
global `loginfo.trace_level` to `loginfo.level`; otherwise it defaults
to `logging.DEBUG`.
* `verbose`: if `None`, then if stderr is a tty then the log
level is `INFO` otherwise `WARNING`. Otherwise, if `verbose` is
true then the log level is `INFO` otherwise `WARNING`.
*`LoggingState.apply(self)`*:
Apply this `LoggingState` to the current logging setup.
## <a name="loginfo"></a>`loginfo = LoggingState(main_log=<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>, level=25, verbose=None, trace_level=10, flags=[], cmd='cs-release', upd=<cs.upd.Upd object at 0x1046a66b0>, upd_mode=True, ansi_mode=True, format='%(pfx)s: %(message)s', supplant_root_logger=False)`
A logging setup arranged for conventional UNIX command line use.
## <a name="LogTime"></a>Class `LogTime`
LogTime is a context manager that logs the elapsed time of the enclosed
code. After the run, the field .elapsed contains the elapsed time in
seconds.
*`LogTime.__init__(self, tag, *args, **kwargs)`*:
Set up a LogTime.
Parameters:
* `tag`: label included at the start of the log entry
* `args`: optional array; if not empty `args` is applied to
`tag` with `%`
* `level`: keyword argument specifying a log level for a
default log entry, default `logging.INFO`
* `threshold`: keyword argument specifying minimum time to
cause a log, default None (no minimum)
* `warning_level`: keyword argument specifying the log level
for a warning log entry, default `logging.WARNING`
* `warning_threshold`: keyword argument specifying a time
which raises the log level to `warning_level`
## <a name="logTo"></a>`logTo(filename, logger=None, mode='a', encoding=None, delay=False, format=None, no_prefix=False)`
Add a `FileHandler` logging to the specified `filename`;
return the chosen logger and the new handler.
Parameters:
* `logger`: if supplied and not `None`, add the `FileHandler` to that
`Logger`, otherwise to the root Logger. If `logger` is a string, call
`logging.getLogger(logger)` to obtain the logger.
* `mode`, `encoding` and `delay`: passed to the `FileHandler`
initialiser.
* `format`: used to override the handler's default format.
* `no_prefix`: if true, do not put the `Pfx` context onto the front of the message.
## <a name="NullHandler"></a>Class `NullHandler(logging.Handler)`
A `Handler` which discards its requests.
*`NullHandler.emit(self, record)`*:
Discard the log record.
## <a name="PfxFormatter"></a>Class `PfxFormatter(logging.Formatter)`
A Formatter subclass that has access to the program's `cmd` and `Pfx` state.
*`PfxFormatter.__init__(self, fmt=None, datefmt=None, cmd=None)`*:
Initialise the `PfxFormatter`.
Parameters:
* `fmt`: format template,
default from `DEFAULT_PFX_FORMAT` `'%(asctime)s %(levelname)s %(pfx)s: %(message)s'`.
Passed through to `Formatter.__init__`.
* `datefmt`:
Passed through to `Formatter.__init__`.
* `cmd`: the "command prefix" made available to format strings.
If not set, `cs.pfx.cmd` is presented.
*`PfxFormatter.format(self, record)`*:
Set `record.cmd` and `record.pfx`
to the global `cmd` and `Pfx` context prefix respectively,
then call `Formatter.format`.
*`PfxFormatter.patch_formatter(formatter)`*:
Monkey patch an existing `Formatter` instance
with a `format` method which prepends the current `Pfx` prefix.
## <a name="quiet"></a>`quiet(msg, *args, **kwargs)`
Emit a log at `QUIET` level with the current `Pfx` prefix.
## <a name="setup_logging"></a>`setup_logging(cmd_name=None, **kw)`
Prepare a `LoggingState` and return it.
It is also available as the global `cs.logutils.loginfo`.
Side-effect: sets `cs.pfx.cmd` to this value.
## <a name="status"></a>`status(msg, *args, **kwargs)`
Emit a log at `STATUS` level with the current `Pfx` prefix.
## <a name="trace"></a>`trace(msg, *args, **kwargs)`
Emit a log message at `loginfo.trace_level` with the current `Pfx` prefix.
## <a name="track"></a>`track(msg, *args, **kwargs)`
Emit a log at `TRACK` level with the current `Pfx` prefix.
## <a name="upd"></a>`upd(msg, *args, **kwargs)`
If we're using an `UpdHandler`,
update the status line otherwise write an info message.
Note that this calls `Upd.out` directly with `msg%args`
and thus does not include the current `Pfx` prefix.
You may well want to use the `status()` function instead.
## <a name="UpdHandler"></a>Class `UpdHandler(logging.StreamHandler)`
A `StreamHandler` subclass whose `.emit` method
uses a `cs.upd.Upd` for transcription.
*`UpdHandler.__init__(self, strm=None, upd_level=None, ansi_mode=None, over_handler=None)`*:
Initialise the `UpdHandler`.
Parameters:
* `strm`: the output stream, default `sys.stderr`.
* `upd_level`: the magic logging level which updates the status line
via `Upd`. Default: `STATUS`.
* `ansi_mode`: if `None`, set from `strm.isatty()`.
A true value causes the handler to colour certain logging levels
using ANSI terminal sequences.
*`UpdHandler.emit(self, logrec)`*:
Emit a `LogRecord` `logrec`.
For the log level `self.upd_level` update the status line.
For other levels write a distinct line
to the output stream, possibly colourised.
*`UpdHandler.flush(self)`*:
Flush the update status.
## <a name="verbose"></a>`verbose(msg, *args, **kwargs)`
Emit a log at `VERBOSE` level with the current `Pfx` prefix.
## <a name="warning"></a>`warning(msg, *args, **kwargs)`
Emit a log at `logging.WARNING` level with the current `Pfx` prefix.
## <a name="with_log"></a>`with_log(filename, **kw)`
Context manager to add a `Logger` to the output logs temporarily.
# Release Log
*Release 20241109*:
* setup_logging: make it work with no arguments.
* ifdebug: handle loginfo.level=None.
*Release 20241007*:
* setup_logging: just amend the existing loginfo if already set up.
* Remove the cs.pfx.cmd side effect from LogState.__init__, now in setup_logging.
*Release 20240923*:
setup_logging: accept leading `cmd_name` for backwards compatibility, reported by Lance Cohen.
*Release 20240630*:
* New LoggingState class for the computed log state, split out setup_logging() as a little stub.
* Drop func_wrap and _ftrace, superceded by cs.debug.trace.
* infer_logging_level: ignore the module.name and module:function_name $DEBUG values, now done by importing cs.debug.
*Release 20230212*:
Late import of cs.upd at need to avoid import loop.
*Release 20220531*:
PfxFormatter.patch_formatter: notice if record.args is not a tuple and do not try to prefix it (for now).
*Release 20220530*:
* New QUIET log level between TRACK and STATUS, add new quiet() logging call.
* PfxFormatter.patch_formatter: bugfix handling of record.msg,record.args.
*Release 20220315*:
A bit of a hack to prevent double patching a formatter, as when BaseCommand calls a BaseCommand and other circumstances where setup_logging() gets called more than once.
*Release 20220227*:
* PfxFormatter: new patch_formatter() static method to modify an existing Formatter.
* setup_logging: just use PfxFormatter.patch_formatter on the first handler's formatter if logging is already set up.
*Release 20211208*:
Docstring update.
*Release 20210721*:
UpdHandler.emit: for newline-emitting messages, fall back to new .over_handler if the Upd is disabled.
*Release 20210718*:
setup_logging: new supplant_root_logger=False parameter to pop the existing handler, typical use supplant_root_logger=sys.stderr.isatty().
*Release 20210306*:
* Default logging level for ttys is now INFO, not STATUS.
* New VERBOSE level below INFO but above DEBUG.
* infer_logging_level: if verbose unspecified, logging=WARNING on a tty and TRACK otherwise, else if verbose, level=VERBOSE, otherwise WARNING.
* Include .verbose in the loginfo.
* New verbose() and ifverbose().
*Release 20201021*:
* setup_logging: always provide loginfo.upd, being either main_handler.upd if upd_mode otherwise Upd().
* exception(): plumb keyword arguments.
*Release 20200729*:
setup_logging: honour $NO_COLOR if ansi_mode not specified, per https://no-color.org/
*Release 20200613*:
* LogTime: set .end on exit.
* UpdHandle.emit: fix message colouring logic.
*Release 20200521*:
setup_logging: include the logger in loginfo (presently always the root logger).
*Release 20200519*:
bugfix setup_logging: apparently a LoggingProxy does not have an encoding
*Release 20200518*:
* Sweeping removal of cs.obj.O, universally supplanted by types.SimpleNamespace.
* Default to logging level TRACK if stderr is a tty instead of logging.INFO.
* New ifverbose function with leading `verbose` parameter: if None, log at INFO otherwise if true, log at TRACK, otherwise do not log.
* BREAKING: remove global logging_level and trace_level variables, put it all in the global loginfo.
* Make STATUS just below TRACK so that it is above INFO instead of below.
* New status() function for cs.upd messages.
* UpdHandler: treat status_level as special, going directly to Upd.out.
* Improved source line recitation on modern Python.
* Default level if sys.stderr.isatty() now STATUS, not TRACK.
* Some fixes for loginfo initialisation and setting cs.pfx.cmd.
*Release 20200229*:
* Update for new Upd.without context manager.
* setup_logging: default `upd_mode` to `main_log.isatty()`, was previously False.
* Drop UpdHandler.upd method, shadowed by instance attribute, never used.
*Release 20190923*:
* New `TRACK` constant equal to `logging.INFO+5` to provide a level higher than `INFO`
* (which seems unreasonably noisy) and lower than `WARNING`
* warning for tracking salient events.
* New `track()` function to match.
*Release 20190220*:
Improvements to upd_mode.
*Release 20190103*:
Documentation updates.
*Release 20190101*:
Bugfix for @contextmanager usage.
*Release 20171030*:
Assorted fixes from recent module reshuffle. Other small features and cleanups. Drop a couple of unused functions.
*Release 20160828*:
Use "install_requires" instead of "requires" in DISTINFO.
*Release 20160827*:
* Pfx: import __exit__ handler
* Preliminary per-module and per-function syntax accepted in $DEBUG envvar.
* Improvements to X(), add DP() and XP() prefixed flavours.
* status() function to update terminal status line.
* New X_via_tty global flag: directs X() to tty instead of sys.stderr.
* Assorted other minor improvements.
*Release 20150118*:
metadata updates
*Release 20150110*:
Initial PyPI release.
Raw data
{
"_id": null,
"home_page": null,
"name": "cs.logutils",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "python2, python3",
"author": null,
"author_email": "Cameron Simpson <cs@cskk.id.au>",
"download_url": "https://files.pythonhosted.org/packages/ed/63/3796bed8a60dd525c48601e6269769e2b9d5d7d48219f28ba1642be4b877/cs_logutils-20241109.tar.gz",
"platform": null,
"description": "Logging convenience routines.\n\n*Latest release 20241109*:\n* setup_logging: make it work with no arguments.\n* ifdebug: handle loginfo.level=None.\n\nThe logging package is very useful, but a little painful to use.\nThis package provides low impact logging setup and some extremely\nuseful if unconventional context hooks for logging.\n\nThe default logging verbosity output format has different defaults\nbased on whether an output log file is a tty\nand whether the environment variable `$DEBUG` is set, and to what.\n\nOn terminals warnings and errors get ANSI colouring.\n\nA mode is available that uses `cs.upd` for certain log levels.\n\nLog messages dispatched via `warning` and friends from this module\nare automatically prefixed with the current `cs.pfx` prefix string,\nproviding automatic message context.\n\nSome examples:\n--------------\n\nProgram initialisation:\n\n from cs.logutils import setup_logging\n\n def main(argv):\n cmd = os.path.basename(argv.pop(0))\n setup_logging(cmd)\n\nBasic logging from anywhere:\n\n from cs.logutils import info, warning, error\n [...]\n def some_function(...):\n [...]\n error(\"nastiness found! bad value=%r\", bad_value)\n\n## <a name=\"add_logfile\"></a>`add_logfile(filename, logger=None, mode='a', encoding=None, delay=False, format=None, no_prefix=False)`\n\nAdd a `FileHandler` logging to the specified `filename`;\nreturn the chosen logger and the new handler.\n\nParameters:\n* `logger`: if supplied and not `None`, add the `FileHandler` to that\n `Logger`, otherwise to the root Logger. If `logger` is a string, call\n `logging.getLogger(logger)` to obtain the logger.\n* `mode`, `encoding` and `delay`: passed to the `FileHandler`\n initialiser.\n* `format`: used to override the handler's default format.\n* `no_prefix`: if true, do not put the `Pfx` context onto the front of the message.\n\n## <a name=\"critical\"></a>`critical(msg, *args, **kwargs)`\n\nEmit a log at `logging.CRITICAL` level with the current `Pfx` prefix.\n\n## <a name=\"D\"></a>`D(msg, *args)`\n\nPrint formatted debug string straight to `sys.stderr` if\n`D_mode` is true, bypassing the logging modules entirely.\nA quick'n'dirty debug tool.\n\n## <a name=\"debug\"></a>`debug(msg, *args, **kwargs)`\n\nEmit a log at `logging.DEBUG` level with the current `Pfx` prefix.\n\n## <a name=\"error\"></a>`error(msg, *args, **kwargs)`\n\nEmit a log at `logging.ERROR` level with the current `Pfx` prefix.\n\n## <a name=\"exception\"></a>`exception(msg, *args, **kwargs)`\n\nEmit an exception log with the current `Pfx` prefix.\n\n## <a name=\"ifdebug\"></a>`ifdebug()`\n\nTest the `loginfo.level` against `logging.DEBUG`.\n\n## <a name=\"ifverbose\"></a>`ifverbose(is_verbose, msg, *args, **kwargs)`\n\nConditionally log a message.\n\nIf `is_verbose` is `None`, log at `VERBOSE` level and rely on the logging setup.\nOtherwise, if `is_verbose` is true, log at `INFO` level.\n\n## <a name=\"infer_logging_level\"></a>`infer_logging_level(env_debug=None, environ=None, verbose=None)`\n\nInfer a logging level from the `env_debug`, which by default\ncomes from the environment variable `$DEBUG`.\n\nUsually default to `logging.WARNING`, but if `sys.stderr` is a terminal,\ndefault to `logging.INFO`.\n\nParse the environment variable `$DEBUG` as a comma separated\nlist of flags.\n\nExamine the in sequence flags to affect the logging level:\n* numeric < 1: `logging.WARNING`\n* numeric >= 1 and < 2: `logging.INFO`\n* numeric >= 2: `logging.DEBUG`\n* `\"DEBUG\"`: `logging.DEBUG`\n* `\"STATUS\"`: `STATUS`\n* `\"INFO\"`: `logging.INFO`\n* `\"TRACK\"`: `TRACK`\n* `\"WARNING\"`: `logging.WARNING`\n* `\"ERROR\"`: `logging.ERROR`\n\nReturn an object with the following attributes:\n* `.level`: A logging level.\n* `.flags`: All the words from `$DEBUG` as separated by commas and uppercased.\n\n## <a name=\"info\"></a>`info(msg, *args, **kwargs)`\n\nEmit a log at `logging.INFO` level with the current `Pfx` prefix.\n\n## <a name=\"log\"></a>`log(level, msg, *args, **kwargs)`\n\nEmit a log at the specified level with the current `Pfx` prefix.\n\n## <a name=\"logException\"></a>`logException(exc_type, exc_value, exc_tb)`\n\nReplacement for `sys.excepthook` that reports via the `cs.logutils`\nlogging wrappers.\n\n## <a name=\"LoggingState\"></a>Class `LoggingState(types.SimpleNamespace)`\n\nA logging setup arranged for conventional UNIX command line use.\n\n*`LoggingState.__init__(self, cmd=None, main_log=None, format=None, level=None, flags=None, upd_mode=None, ansi_mode=None, trace_mode=None, verbose=None, supplant_root_logger=False)`*:\nPrepare the `LoggingState` for conventional UNIX command\nline error messaging.\n\nAmongst other things, the default logger now includes\nthe `cs.pfx` prefix in the message.\n\nThis function runs in two modes:\n- if logging has not been set up, it sets up a root logger\n- if the root logger already has handlers,\n monkey patch the first handler's formatter to prefix the `cs.pfx` state\n\nParameters:\n* `cmd`: program name, default from `basename(sys.argv[0])`.\n* `main_log`: default logging system.\n If `None`, the main log will go to `sys.stderr`;\n if `main_log` is a string, is it used as a filename to\n open in append mode;\n otherwise main_log should be a stream suitable\n for use with `logging.StreamHandler()`.\n The resulting log handler is added to the `logging` root logger.\n* `format`: the message format for `main_log`.\n If `None`, use `DEFAULT_PFX_FORMAT_TTY`\n when `main_log` is a tty or FIFO,\n otherwise `DEFAULT_PFX_FORMAT`.\n* `level`: `main_log` logging level.\n If `None`, infer a level from the environment\n using `infer_logging_level()`.\n* `flags`: a string containing debugging flags separated by commas.\n If `None`, infer the flags from the environment using\n `infer_logging_level()`.\n The following flags have meaning:\n `D`: set cs.logutils.D_mode to True;\n `TDUMP`: attach a signal handler to SIGHUP to do a thread stack dump;\n `TRACE`: enable various noisy tracing facilities;\n `UPD`, `NOUPD`: set the default for `upd_mode` to True or False respectively.\n* `upd_mode`: a Boolean to activate cs.upd as the `main_log` method;\n if `None`, set it to `True` if `flags` contains 'UPD',\n otherwise to `False` if `flags` contains 'NOUPD',\n otherwise set it from `main_log.isatty()`.\n A true value causes the root logger to use `cs.upd` for logging.\n* `ansi_mode`: if `None`,\n set it from `main_log.isatty() and not cs.colourise.env_no_color()`,\n which thus honours the `$NO_COLOR` environment variable\n (see https://no-color.org/ for the convention).\n A true value causes the root logger to colour certain logging levels\n using ANSI terminal sequences (currently only if `cs.upd` is used).\n* `trace_mode`: if `None`, set it according to the presence of\n 'TRACE' in flags. Otherwise if `trace_mode` is true, set the\n global `loginfo.trace_level` to `loginfo.level`; otherwise it defaults\n to `logging.DEBUG`.\n* `verbose`: if `None`, then if stderr is a tty then the log\n level is `INFO` otherwise `WARNING`. Otherwise, if `verbose` is\n true then the log level is `INFO` otherwise `WARNING`.\n\n*`LoggingState.apply(self)`*:\nApply this `LoggingState` to the current logging setup.\n\n## <a name=\"loginfo\"></a>`loginfo = LoggingState(main_log=<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>, level=25, verbose=None, trace_level=10, flags=[], cmd='cs-release', upd=<cs.upd.Upd object at 0x1046a66b0>, upd_mode=True, ansi_mode=True, format='%(pfx)s: %(message)s', supplant_root_logger=False)`\n\nA logging setup arranged for conventional UNIX command line use.\n\n## <a name=\"LogTime\"></a>Class `LogTime`\n\nLogTime is a context manager that logs the elapsed time of the enclosed\ncode. After the run, the field .elapsed contains the elapsed time in\nseconds.\n\n*`LogTime.__init__(self, tag, *args, **kwargs)`*:\nSet up a LogTime.\n\nParameters:\n* `tag`: label included at the start of the log entry\n* `args`: optional array; if not empty `args` is applied to\n `tag` with `%`\n* `level`: keyword argument specifying a log level for a\n default log entry, default `logging.INFO`\n* `threshold`: keyword argument specifying minimum time to\n cause a log, default None (no minimum)\n* `warning_level`: keyword argument specifying the log level\n for a warning log entry, default `logging.WARNING`\n* `warning_threshold`: keyword argument specifying a time\n which raises the log level to `warning_level`\n\n## <a name=\"logTo\"></a>`logTo(filename, logger=None, mode='a', encoding=None, delay=False, format=None, no_prefix=False)`\n\nAdd a `FileHandler` logging to the specified `filename`;\nreturn the chosen logger and the new handler.\n\nParameters:\n* `logger`: if supplied and not `None`, add the `FileHandler` to that\n `Logger`, otherwise to the root Logger. If `logger` is a string, call\n `logging.getLogger(logger)` to obtain the logger.\n* `mode`, `encoding` and `delay`: passed to the `FileHandler`\n initialiser.\n* `format`: used to override the handler's default format.\n* `no_prefix`: if true, do not put the `Pfx` context onto the front of the message.\n\n## <a name=\"NullHandler\"></a>Class `NullHandler(logging.Handler)`\n\nA `Handler` which discards its requests.\n\n*`NullHandler.emit(self, record)`*:\nDiscard the log record.\n\n## <a name=\"PfxFormatter\"></a>Class `PfxFormatter(logging.Formatter)`\n\nA Formatter subclass that has access to the program's `cmd` and `Pfx` state.\n\n*`PfxFormatter.__init__(self, fmt=None, datefmt=None, cmd=None)`*:\nInitialise the `PfxFormatter`.\n\nParameters:\n* `fmt`: format template,\n default from `DEFAULT_PFX_FORMAT` `'%(asctime)s %(levelname)s %(pfx)s: %(message)s'`.\n Passed through to `Formatter.__init__`.\n* `datefmt`:\n Passed through to `Formatter.__init__`.\n* `cmd`: the \"command prefix\" made available to format strings.\n If not set, `cs.pfx.cmd` is presented.\n\n*`PfxFormatter.format(self, record)`*:\nSet `record.cmd` and `record.pfx`\nto the global `cmd` and `Pfx` context prefix respectively,\nthen call `Formatter.format`.\n\n*`PfxFormatter.patch_formatter(formatter)`*:\nMonkey patch an existing `Formatter` instance\nwith a `format` method which prepends the current `Pfx` prefix.\n\n## <a name=\"quiet\"></a>`quiet(msg, *args, **kwargs)`\n\nEmit a log at `QUIET` level with the current `Pfx` prefix.\n\n## <a name=\"setup_logging\"></a>`setup_logging(cmd_name=None, **kw)`\n\nPrepare a `LoggingState` and return it.\nIt is also available as the global `cs.logutils.loginfo`.\nSide-effect: sets `cs.pfx.cmd` to this value.\n\n## <a name=\"status\"></a>`status(msg, *args, **kwargs)`\n\nEmit a log at `STATUS` level with the current `Pfx` prefix.\n\n## <a name=\"trace\"></a>`trace(msg, *args, **kwargs)`\n\nEmit a log message at `loginfo.trace_level` with the current `Pfx` prefix.\n\n## <a name=\"track\"></a>`track(msg, *args, **kwargs)`\n\nEmit a log at `TRACK` level with the current `Pfx` prefix.\n\n## <a name=\"upd\"></a>`upd(msg, *args, **kwargs)`\n\nIf we're using an `UpdHandler`,\nupdate the status line otherwise write an info message.\n\nNote that this calls `Upd.out` directly with `msg%args`\nand thus does not include the current `Pfx` prefix.\nYou may well want to use the `status()` function instead.\n\n## <a name=\"UpdHandler\"></a>Class `UpdHandler(logging.StreamHandler)`\n\nA `StreamHandler` subclass whose `.emit` method\nuses a `cs.upd.Upd` for transcription.\n\n*`UpdHandler.__init__(self, strm=None, upd_level=None, ansi_mode=None, over_handler=None)`*:\nInitialise the `UpdHandler`.\n\nParameters:\n* `strm`: the output stream, default `sys.stderr`.\n* `upd_level`: the magic logging level which updates the status line\n via `Upd`. Default: `STATUS`.\n* `ansi_mode`: if `None`, set from `strm.isatty()`.\n A true value causes the handler to colour certain logging levels\n using ANSI terminal sequences.\n\n*`UpdHandler.emit(self, logrec)`*:\nEmit a `LogRecord` `logrec`.\n\nFor the log level `self.upd_level` update the status line.\nFor other levels write a distinct line\nto the output stream, possibly colourised.\n\n*`UpdHandler.flush(self)`*:\nFlush the update status.\n\n## <a name=\"verbose\"></a>`verbose(msg, *args, **kwargs)`\n\nEmit a log at `VERBOSE` level with the current `Pfx` prefix.\n\n## <a name=\"warning\"></a>`warning(msg, *args, **kwargs)`\n\nEmit a log at `logging.WARNING` level with the current `Pfx` prefix.\n\n## <a name=\"with_log\"></a>`with_log(filename, **kw)`\n\nContext manager to add a `Logger` to the output logs temporarily.\n\n# Release Log\n\n\n\n*Release 20241109*:\n* setup_logging: make it work with no arguments.\n* ifdebug: handle loginfo.level=None.\n\n*Release 20241007*:\n* setup_logging: just amend the existing loginfo if already set up.\n* Remove the cs.pfx.cmd side effect from LogState.__init__, now in setup_logging.\n\n*Release 20240923*:\nsetup_logging: accept leading `cmd_name` for backwards compatibility, reported by Lance Cohen.\n\n*Release 20240630*:\n* New LoggingState class for the computed log state, split out setup_logging() as a little stub.\n* Drop func_wrap and _ftrace, superceded by cs.debug.trace.\n* infer_logging_level: ignore the module.name and module:function_name $DEBUG values, now done by importing cs.debug.\n\n*Release 20230212*:\nLate import of cs.upd at need to avoid import loop.\n\n*Release 20220531*:\nPfxFormatter.patch_formatter: notice if record.args is not a tuple and do not try to prefix it (for now).\n\n*Release 20220530*:\n* New QUIET log level between TRACK and STATUS, add new quiet() logging call.\n* PfxFormatter.patch_formatter: bugfix handling of record.msg,record.args.\n\n*Release 20220315*:\nA bit of a hack to prevent double patching a formatter, as when BaseCommand calls a BaseCommand and other circumstances where setup_logging() gets called more than once.\n\n*Release 20220227*:\n* PfxFormatter: new patch_formatter() static method to modify an existing Formatter.\n* setup_logging: just use PfxFormatter.patch_formatter on the first handler's formatter if logging is already set up.\n\n*Release 20211208*:\nDocstring update.\n\n*Release 20210721*:\nUpdHandler.emit: for newline-emitting messages, fall back to new .over_handler if the Upd is disabled.\n\n*Release 20210718*:\nsetup_logging: new supplant_root_logger=False parameter to pop the existing handler, typical use supplant_root_logger=sys.stderr.isatty().\n\n*Release 20210306*:\n* Default logging level for ttys is now INFO, not STATUS.\n* New VERBOSE level below INFO but above DEBUG.\n* infer_logging_level: if verbose unspecified, logging=WARNING on a tty and TRACK otherwise, else if verbose, level=VERBOSE, otherwise WARNING.\n* Include .verbose in the loginfo.\n* New verbose() and ifverbose().\n\n*Release 20201021*:\n* setup_logging: always provide loginfo.upd, being either main_handler.upd if upd_mode otherwise Upd().\n* exception(): plumb keyword arguments.\n\n*Release 20200729*:\nsetup_logging: honour $NO_COLOR if ansi_mode not specified, per https://no-color.org/\n\n*Release 20200613*:\n* LogTime: set .end on exit.\n* UpdHandle.emit: fix message colouring logic.\n\n*Release 20200521*:\nsetup_logging: include the logger in loginfo (presently always the root logger).\n\n*Release 20200519*:\nbugfix setup_logging: apparently a LoggingProxy does not have an encoding\n\n*Release 20200518*:\n* Sweeping removal of cs.obj.O, universally supplanted by types.SimpleNamespace.\n* Default to logging level TRACK if stderr is a tty instead of logging.INFO.\n* New ifverbose function with leading `verbose` parameter: if None, log at INFO otherwise if true, log at TRACK, otherwise do not log.\n* BREAKING: remove global logging_level and trace_level variables, put it all in the global loginfo.\n* Make STATUS just below TRACK so that it is above INFO instead of below.\n* New status() function for cs.upd messages.\n* UpdHandler: treat status_level as special, going directly to Upd.out.\n* Improved source line recitation on modern Python.\n* Default level if sys.stderr.isatty() now STATUS, not TRACK.\n* Some fixes for loginfo initialisation and setting cs.pfx.cmd.\n\n*Release 20200229*:\n* Update for new Upd.without context manager.\n* setup_logging: default `upd_mode` to `main_log.isatty()`, was previously False.\n* Drop UpdHandler.upd method, shadowed by instance attribute, never used.\n\n*Release 20190923*:\n* New `TRACK` constant equal to `logging.INFO+5` to provide a level higher than `INFO`\n* (which seems unreasonably noisy) and lower than `WARNING`\n* warning for tracking salient events.\n* New `track()` function to match.\n\n*Release 20190220*:\nImprovements to upd_mode.\n\n*Release 20190103*:\nDocumentation updates.\n\n*Release 20190101*:\nBugfix for @contextmanager usage.\n\n*Release 20171030*:\nAssorted fixes from recent module reshuffle. Other small features and cleanups. Drop a couple of unused functions.\n\n*Release 20160828*:\nUse \"install_requires\" instead of \"requires\" in DISTINFO.\n\n*Release 20160827*:\n* Pfx: import __exit__ handler\n* Preliminary per-module and per-function syntax accepted in $DEBUG envvar.\n* Improvements to X(), add DP() and XP() prefixed flavours.\n* status() function to update terminal status line.\n* New X_via_tty global flag: directs X() to tty instead of sys.stderr.\n* Assorted other minor improvements.\n\n*Release 20150118*:\nmetadata updates\n\n*Release 20150110*:\nInitial PyPI release.\n",
"bugtrack_url": null,
"license": "GNU General Public License v3 or later (GPLv3+)",
"summary": "Logging convenience routines.",
"version": "20241109",
"project_urls": {
"MonoRepo Commits": "https://bitbucket.org/cameron_simpson/css/commits/branch/main",
"Monorepo Git Mirror": "https://github.com/cameron-simpson/css",
"Monorepo Hg/Mercurial Mirror": "https://hg.sr.ht/~cameron-simpson/css",
"Source": "https://github.com/cameron-simpson/css/blob/main/lib/python/cs/logutils.py"
},
"split_keywords": [
"python2",
" python3"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "0f426e1e7f9b40d8ac7ff6e4f31190866bc71144a5b9b9d43535943100d227a9",
"md5": "29c463d0f9f02d5a958faa09373402c3",
"sha256": "2f435df577d0b08d941791529d7696c25c353a2438b996ffa49b6425f1032016"
},
"downloads": -1,
"filename": "cs.logutils-20241109-py3-none-any.whl",
"has_sig": false,
"md5_digest": "29c463d0f9f02d5a958faa09373402c3",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 14869,
"upload_time": "2024-11-08T22:03:05",
"upload_time_iso_8601": "2024-11-08T22:03:05.126697Z",
"url": "https://files.pythonhosted.org/packages/0f/42/6e1e7f9b40d8ac7ff6e4f31190866bc71144a5b9b9d43535943100d227a9/cs.logutils-20241109-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ed633796bed8a60dd525c48601e6269769e2b9d5d7d48219f28ba1642be4b877",
"md5": "801bb8dbdd99ff76d64a34b6a1d8bbe7",
"sha256": "8da10b548f5d17ed6c89d5a1cf4cb5e6c353b4a8b96e3eff62fdff9f69e5f8cb"
},
"downloads": -1,
"filename": "cs_logutils-20241109.tar.gz",
"has_sig": false,
"md5_digest": "801bb8dbdd99ff76d64a34b6a1d8bbe7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 17217,
"upload_time": "2024-11-08T22:03:07",
"upload_time_iso_8601": "2024-11-08T22:03:07.177577Z",
"url": "https://files.pythonhosted.org/packages/ed/63/3796bed8a60dd525c48601e6269769e2b9d5d7d48219f28ba1642be4b877/cs_logutils-20241109.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-08 22:03:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "cameron-simpson",
"github_project": "css",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "cs.logutils"
}