clog/clog/utils/printfmt.py
theonepath 3fe521bcf5
Updated files to flake8 standard
Files have been changed to ensure they abid flake8 defined rules that
have not been identified as ignored. Files mostly pass flake8 rules.
2022-05-04 01:13:13 +01:00

114 lines
3.8 KiB
Python

import textwrap
import time
from typing import Union
from .common import LogLevel
## log message constant format template
__LOG_TMPL = "[{DATE}] [{0}] {TYPE} "
## string time format (ISO: 8601, long-form)
__TIMESTAMP_FMT = "%Y-%m-%dT%H:%M:%S%z"
class Colours:
NORMAL = '\033[0m'
RED = '\033[91m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
BLUE = '\033[94m'
def loglevel_as_str(level: Union[LogLevel, int]) -> str:
"""Convert an integer or enum value into its appropriate enum
attribute name.
`@Params`: level - `LogLevel | int`
`Returns`: LogLevel enum literal attribute name - `str`
"""
## perform a lookup of each attribute of LogLevel and its associate
## value, and search for the attribute that has the matching level
## value passed to the function.
_attrs = [_dir for _dir in dir(LogLevel)
if not _dir.startswith('__')] # list of all attributes of LogLevel
for _ in _attrs: # iterate over all attributes defined
if getattr(LogLevel, _) == level: # if the level matches
return "{0: <5}".format(_) # return the attribute name
return " " * 5
def log_as_col(level: Union[int, LogLevel]) -> Colours:
"""Convert an integer or enum value into an associated ANSI escape
code terminal colour sequence. Depending on log level severity, an
associated colour is returned to give STDOUT text a distinct
separation of colour from regular STDOUT text.
`@Params`: level - `LogLevel | int`
`@Return`: Enum of `Colours`
"""
## perform a colour lookup based on level number
if level == LogLevel.DEBUG:
return Colours.BLUE
elif level == LogLevel.WARN:
return Colours.YELLOW
elif level == LogLevel.ERROR:
return Colours.RED
elif level == LogLevel.PASS:
return Colours.GREEN
else:
return Colours.NORMAL
def gen_log_header(_type: Union[LogLevel, int, str]) -> str:
"""Generate a header string for use of standardising log outputs.
The header is defined using the following standard header:
```plaintext
"[YYYY-MM-DDTHH:MM:SS+OFFSET] [{CALLER}] <LogLevel> {0}"
```
The first column defines the Date-Time following the ISO 8601 (long)
standard timestamp format, whereby `T` is the separator between Date
and Time. The `+OFFSET` is the number of hours ahead/behind UTC, the
currently timezone set by the PC. This is achieved using the following
string to time format:
`%Y-%m-%dT%H:%M:%S%z`.
The second column is reversed during the return value of the string.
This column is used to allow for a stacktrace to be attached to the
log message.
The third column defines the level of the log message. This will be
five blank space characters if a level is passed outside of the
defined scope of logging levels.
The fourth column is reserved during the return value of the string.
It represents the body of the message to be logged.
`@Params`: _type - `LogLevel | int | str`
`@Return`: Formattable string - `str`
"""
## if the _type represents a LogLevel value, convert it to str
if not isinstance(_type, str):
_type = loglevel_as_str(_type)
## return newly formatted log message header
return __LOG_TMPL.format('{CALLER}', DATE=\
time.strftime(__TIMESTAMP_FMT, time.localtime()),
TYPE=_type) + "{0}"
def wrap(value: str, *, width: int = 120, tb_size: int = 4) -> str:
"""Return a hard-wrapped string defined by a fixed width.
Wrapped text is separated by a `\\n` character and a fixed width of
120 characters. Each wrap is appended with a tab size of 4 characters
at the start of each line-wrap.
`@Params`: value - `str`, width = 120 - `int`, tb_size = 4 - `int`
`@Return`: `str`
"""
return "\n".join(textwrap.wrap(value, width=width, tabsize=tb_size))