Files
tradon/tools/logging.py
2025-12-26 13:11:43 +00:00

127 lines
3.6 KiB
Python
Executable File

from collections.abc import Iterable, Mapping
from itertools import islice
_MAX_ARGUMENTS = 5
_MAX_ITEMS = 5
_ELLIPSE = '...'
_MAX_STR_LENGTH = 20 - len(_ELLIPSE)
class Ellipse:
__slots__ = ('text',)
def __init__(self, text=_ELLIPSE):
self.text = text
def __str__(self):
return self.text
__repr__ = __str__
class EllipseDict:
__slots__ = ('items',)
def __init__(self, items):
self.items = items
def __str__(self):
strings = []
ellipse = False
for key, value in self.items:
if isinstance(key, Ellipse):
ellipse = True
break
strings.append(f'{key!r}: {value!r}')
if ellipse:
strings.append(_ELLIPSE)
s = ', '.join(strings)
return '{' + s + '}'
__repr__ = __str__
class format_args:
__slots__ = ('args', 'kwargs', 'verbose', 'max_args', 'max_items')
def __init__(self, args, kwargs, verbose=False,
max_args=_MAX_ARGUMENTS, max_items=_MAX_ITEMS):
self.args = args
self.kwargs = kwargs
self.verbose = verbose
self.max_args = max_args
self.max_items = max_items
def __str__(self):
_nb_args = self.max_args
_nb_items = self.max_items
def _shorten_sequence(value):
nonlocal _nb_items
for v in islice(value, None, self.max_items + 1):
if not self.verbose and not _nb_items:
yield Ellipse()
break
yield v
_nb_items -= 1
def _log_repr(value):
if self.verbose:
return value
elif isinstance(value, bytes):
return Ellipse(f'<{len(value)} bytes>')
elif isinstance(value, str):
if len(value) <= _MAX_STR_LENGTH:
return value
return (value[:_MAX_STR_LENGTH]
+ (_ELLIPSE if len(value) > _MAX_STR_LENGTH else ''))
elif isinstance(value, Mapping):
def shorten(value):
for items in _shorten_sequence(value.items()):
if isinstance(items, Ellipse):
yield Ellipse(), Ellipse()
break
key, value = items
yield _log_repr(key), _log_repr(value)
return EllipseDict(shorten(value))
elif isinstance(value, Iterable):
return type(value)(_log_repr(v)
for v in _shorten_sequence(value))
else:
return value
s = '('
logged_args = []
for args in self.args:
if not _nb_args and not self.verbose:
logged_args.append(Ellipse())
break
_nb_items = self.max_items
logged_args.append(_log_repr(args))
_nb_args -= 1
s += ', '.join(repr(a) for a in logged_args)
if self.kwargs and (not logged_args
or not isinstance(logged_args[-1], Ellipse)):
s += ', ' if self.args and self.kwargs else ''
logged_kwargs = []
for key, value in self.kwargs.items():
if not _nb_args and not self.verbose:
logged_kwargs.append(repr(Ellipse()))
break
_nb_items = self.max_items
logged_kwargs.append(
f'{_log_repr(key)}={_log_repr(value)!r}')
_nb_args -= 1
s += ', '.join(logged_kwargs)
s += ')'
return s