Decorator for logging function arguments and return value by human-readable way
Project description
logwrap
logwrap is a helper for logging in human-readable format function arguments and call result on function call. Why? Because logging of *args, **kwargs become useless with project grow and you need more details in call log.
Cons:
Log records are not single line.
Pros:
Log records are not single 100500 symbols length line. (Especially actual for testing/development environments and for Kibana users).
Service free: job is done by this library and it’s dependencies. It works at virtualenv
Free software: Apache license
Open Source: https://github.com/penguinolog/logwrap
PyPI packaged: https://pypi.python.org/pypi/logwrap
Self-documented code: docstrings with types in comments
Tested: see bages on top
Support multiple Python versions:
Python 2.7 Python 3.4 Python 3.5 Python 3.6 PyPy PyPy3 3.5+
This package includes helpers:
logwrap - main helper. The same is LogWrap.
LogWrap - class with logwrap implementation. May be used directly.
pretty_repr
pretty_str
PrettyFormat
Usage
logwrap
The main decorator. Could be used as not argumented (@logwrap.logwrap) and argumented (@logwrap.logwrap()). Not argumented usage simple calls with default values for all positions. Argumented usage with arguments from signature:
@logwrap.logwrap(
log=logging.getLogger(__name__), # __name__ = 'logwrap'
log_level=logging.DEBUG,
exc_level=logging.ERROR,
max_indent=20, # forwarded to the pretty_repr
spec=None, # use target callable function for spec
blacklisted_names=None, # list argument names, which should be dropped from log
blacklisted_exceptions=None, # Exceptions to skip in log
log_call_args=True, # Log call arguments before call
log_call_args_on_exc=True, # Log call arguments if exception happens
log_result_obj=True, # Log result object
)
Usage examples:
@logwrap.logwrap()
def foo():
pass
is equal to:
@logwrap.logwrap
def foo():
pass
Get decorator for use without parameters:
get_logs = logwrap.logwrap() # set required parameters via arguments
type(get_logs) == LogWrap # All logic is implemented in LogWrap class starting from version 2.2.0
@get_logs
def foo():
pass
Call example:
import logwrap
@logwrap.logwrap
def example_function1(
arg1: str,
arg2: str='arg2',
*args,
kwarg1: str,
kwarg2: str='kwarg2',
**kwargs
) -> tuple():
return (arg1, arg2, args, kwarg1, kwarg2, kwargs)
example_function1('arg1', kwarg1='kwarg1', kwarg3='kwarg3')
This code during execution will produce log records:
Calling: 'example_function1'( # POSITIONAL_OR_KEYWORD: 'arg1'=u'''arg1''', 'arg2'=u'''arg2''', # VAR_POSITIONAL: 'args'=(), # KEYWORD_ONLY: 'kwarg1'=u'''kwarg1''', 'kwarg2'=u'''kwarg2''', # VAR_KEYWORD: 'kwargs'= dict({ 'kwarg3': u'''kwarg3''', }), ) Done: 'example_function1' with result: tuple(( u'''arg1''', u'''arg2''', (), u'''kwarg1''', u'''kwarg2''', dict({ 'kwarg3': u'''kwarg3''', }), ))
Limitations:
nested wrapping (@logwrap @deco2 …) is not parsed under python 2.7: functools.wraps limitation. Please set logwrap as the first level decorator.
LogWrap
Example construction and read from test:
log_call = logwrap.LogWrap()
log_call.log_level == logging.DEBUG
log_call.exc_level == logging.ERROR
log_call.max_indent == 20
log_call.blacklisted_names == []
log_call.blacklisted_exceptions == []
log_call.log_call_args == True
log_call.log_call_args_on_exc == True
log_call.log_result_obj == True
On object change, variable types is validated.
pretty_repr
This is specified helper for making human-readable repr on complex objects. Signature is self-documenting:
def pretty_repr(
src, # object for repr
indent=0, # start indent
no_indent_start=False, # do not indent the first level
max_indent=20, # maximum allowed indent level
indent_step=4, # step between indents
py2_str=False, # use bytes for python 2 __repr__ and __str__
)
Limitation: Dict like objects is always marked inside {} for readability, even if it is collections.OrderedDict (standard repr as list of tuples).
pretty_str
This is specified helper for making human-readable str on complex objects. Signature is self-documenting:
def pretty_str(
src, # object for __str__
indent=0, # start indent
no_indent_start=False, # do not indent the first level
max_indent=20, # maximum allowed indent level
indent_step=4, # step between indents
py2_str=False, # use bytes for python 2 __repr__ and __str__
)
- Limitations:
Dict like objects is always marked inside {} for readability, even if it is collections.OrderedDict (standard repr as list of tuples).
Iterable types is not declared, only brackets is used.
String and bytes looks the same (its __str__, not __repr__).
PrettyFormat
PrettyFormat is the main formatting implementation class. pretty_repr and pretty_str uses instances of subclasses PrettyRepr and PrettyStr from this class. This class is mostly exposed for typing reasons. Object signature:
def __init__(
self,
max_indent=20, # maximum allowed indent level
indent_step=4, # step between indents
py2_str=False, # use bytes for python 2 __repr__ and __str__
)
Callable object (PrettyFormat instance) signature:
def __call__(
self,
src, # object for repr
indent=0, # start indent
no_indent_start=False # do not indent the first level
)
Adopting your code
pretty_repr behavior could be overridden for your classes by implementing specific magic method:
def __pretty_repr__(
self,
parser # PrettyFormat class instance,
indent # start indent,
no_indent_start # do not indent the first level
):
return ...
This method will be executed instead of __repr__ on your object.
def __pretty_str__(
self,
parser # PrettyFormat class instance,
indent # start indent,
no_indent_start # do not indent the first level
):
return ...
This method will be executed instead of __str__ on your object.
Testing
The main test mechanism for the package logwrap is using tox. Test environments available:
pep8 py27 py34 py35 py36 pypy pypy3 pylint pep257 docs
CI systems
For code checking several CI systems is used in parallel:
Travis CI: is used for checking: PEP8, pylint, bandit, installation possibility and unit tests. Also it’s publishes coverage on coveralls.
AppVeyor: is used for checking windows compatibility.
coveralls: is used for coverage display.
CD system
Travis CI: is used for package delivery on PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Hashes for logwrap-3.2.1-cp36-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 90557edbcc4cbb964f0dabfdf40f50ed6fdc0bd8e5c7a24a6dc93332aad088f4 |
|
MD5 | 9f725efcb81ba51983f1cfb4ef78d067 |
|
BLAKE2b-256 | 90c5246f893476948641652854d475e153ea7ba0b0250e1369f8331019b471fb |
Hashes for logwrap-3.2.1-cp36-none-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8fd587ddbab4a399b719c6cbae59f9c71f097825cddc5775efe987ffa03d9745 |
|
MD5 | 969dab028e2f4992630365bc25245d89 |
|
BLAKE2b-256 | 17d4db0e5469f2c14046a78021e212ada89e7d8baceeacc0bc9bebc002a8c537 |
Hashes for logwrap-3.2.1-cp36-cp36m-manylinux1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f9303b9a13fa6b552a3d7612367e061d32996d1383676b74c7e07599d05902d5 |
|
MD5 | 89c966055dd1caff521d7902514ce604 |
|
BLAKE2b-256 | b531b998825b15b7b93ae0c9f45e904fadcebff3a5e2a0714b9cee7f4572eff3 |
Hashes for logwrap-3.2.1-cp36-cp36m-manylinux1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a29d517a101ca7d83c8265cf770c33033a329dfaddc24404ad2a5427b77974c5 |
|
MD5 | 5ccaea52a5a835358217d68b83701ab1 |
|
BLAKE2b-256 | 4e5d9a5d116dcd31bc5fa5dea9114fc596d5ad04fef15bbe70a68eff8bbc94ab |
Hashes for logwrap-3.2.1-cp35-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 524769bf6aff84fab91a72e832dd6d1899d9179c38d81446f3afcf7242582c76 |
|
MD5 | 489fc2c64f8df197c0ad4e1737977220 |
|
BLAKE2b-256 | d4163db97309feaccfa982bd82e570761d45d36caacb1457a977fce224f82db0 |
Hashes for logwrap-3.2.1-cp35-none-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b2cc354ef30a88c0ff31545b41f877d1838aef377818c25eaddafe9c7f6b0c83 |
|
MD5 | 9642dc30a36d5568708f58e4b1e9dcc1 |
|
BLAKE2b-256 | 9ddfb9ca3f7d1ce1e92bffb1a94b9eb7e4edbede8a87f185610cdd37c49c707f |
Hashes for logwrap-3.2.1-cp35-cp35m-manylinux1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a46ffa63718b1192b0ce6426796d0c6a063009203c842e81003091883c15e825 |
|
MD5 | ca9cd429b026fb9de360d7f99b3d6e09 |
|
BLAKE2b-256 | 709022cd6a42f568ec3a70a71ec973cd9e05129b974406f864e6c54dcad17768 |
Hashes for logwrap-3.2.1-cp35-cp35m-manylinux1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4f6ac77fe0f08214922ab7f5fa0d93e103ba74ac3dd029f27afe130ae428d0c1 |
|
MD5 | 9b5c106c7e5e08d3ad92bd980009ee29 |
|
BLAKE2b-256 | 56cb16bf2ec49d40c525d38b562a6373c96ef4f9fa430b5bded5db4f9e6af5c0 |
Hashes for logwrap-3.2.1-cp34-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 965bc05921e762ee07d163f5fc5cdfbadbcaea59fb6f9089259c9e68e8f0ae6d |
|
MD5 | e6c88bfbeb9ad3d29d5cac7ec831e5cc |
|
BLAKE2b-256 | 2b8be94ffdf9b6843b705f8179deacc39fffc94a1e576e6555a49beb7860c48f |
Hashes for logwrap-3.2.1-cp34-none-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 77c9a50d31e56a8d377a10dbcce0c96496e3cd62dced99b3f2bb184a5967bde7 |
|
MD5 | 82b3c41834dd55e903ae0162f8bcbb40 |
|
BLAKE2b-256 | bc7b785cb33c85a7a51a42fe517a6c619edc36fbec5a040e67d1e3fbf9571ea3 |
Hashes for logwrap-3.2.1-cp34-cp34m-manylinux1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7954e6fd6178f9d0556dcc76a88d35a22818c3bcfec5f3baf1e9db0b62c781cb |
|
MD5 | da3f4a9b4941f5246a264bcf96842ddf |
|
BLAKE2b-256 | 09f60d269e8b88d6d69f3e43f5a9f34929b3eb6c0c6dd1013ae860bf55852ec4 |
Hashes for logwrap-3.2.1-cp34-cp34m-manylinux1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f686244037a76d65927224f95d1953e4ff95a0b15f6699c006f2cdb332de2e35 |
|
MD5 | d937412396298213008625847f10c079 |
|
BLAKE2b-256 | affb5cc79d3cc2d6a0e50c8d54feb88520ee19a70466ad8520b02a9fbae418ea |