Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
.. image:: https://github.com/python-useful-helpers/logwrap/workflows/Python%20package/badge.svg :target: https://github.com/python-useful-helpers/logwrap/actions .. image:: https://coveralls.io/repos/github/python-useful-helpers/logwrap/badge.svg?branch=master :target: https://coveralls.io/github/python-useful-helpers/logwrap?branch=master .. image:: https://readthedocs.org/projects/logwrap/badge/?version=latest :target: http://logwrap.readthedocs.io/ :alt: Documentation Status .. image:: https://img.shields.io/pypi/v/logwrap.svg :target: https://pypi.python.org/pypi/logwrap .. image:: https://img.shields.io/pypi/pyversions/logwrap.svg :target: https://pypi.python.org/pypi/logwrap .. image:: https://img.shields.io/pypi/status/logwrap.svg :target: https://pypi.python.org/pypi/logwrap .. image:: https://img.shields.io/github/license/python-useful-helpers/logwrap.svg :target: https://raw.githubusercontent.com/python-useful-helpers/logwrap/master/LICENSE .. image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/ambv/black
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:
Pros:
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
LogOnAccess
- property with logging on successful get/set/delete or failure.
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.
.. note:: Argumens should be set via keywords only.
Argumented usage with arguments from signature:
.. code-block:: python
@logwrap.logwrap(
log=None, # if not set: try to find LOGGER, LOG, logger or log object in target module and use it if it logger instance. Fallback: logger named logwrap
log_level=logging.DEBUG,
exc_level=logging.ERROR,
max_indent=20, # forwarded to the pretty_repr,
max_iter=0, # forwarded to the pretty_repr, max number of items in the Iterable before ellipsis. Unlimited if 0.
blacklisted_names=None, # list argument names, which should be dropped from log
blacklisted_exceptions=None, # Exceptions to skip details in log (no traceback, no exception details - just class name)
log_call_args=True, # Log call arguments before call
log_call_args_on_exc=True, # Log call arguments if exception happens
log_traceback = True, # Log traceback if exception happens
log_result_obj=True, # Log result object
)
Usage examples:
.. code-block:: python
@logwrap.logwrap()
def foo():
pass
is equal to:
.. code-block:: python
@logwrap.logwrap
def foo():
pass
Get decorator for use without parameters:
.. code-block:: python
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 (python 3.8):
.. code-block:: python
import logwrap
@logwrap.logwrap def example_function1( arg0: str, /, arg1: str, arg2: str='arg2', *args, kwarg1: str, kwarg2: str='kwarg2', **kwargs ) -> tuple(): return (arg0, arg1, arg2, args, kwarg1, kwarg2, kwargs)
example_function1('arg0', 'arg1', kwarg1='kwarg1', kwarg3='kwarg3')
This code during execution will produce log records:
::
Calling:
'example_function1'(
# POSITIONAL_ONLY:
arg0='arg0', # type: str
# POSITIONAL_OR_KEYWORD:
arg1='arg1', # type: str
arg2='arg2', # type: str
# VAR_POSITIONAL:
args=(),
# KEYWORD_ONLY:
kwarg1='kwarg1', # type: str
kwarg2='kwarg2', # type: str
# VAR_KEYWORD:
kwargs={
'kwarg3': 'kwarg3',
},
)
Done: 'example_function1' with result:
(
'arg0',
'arg1',
'arg2',
(),
'kwarg1',
'kwarg2',
{
'kwarg3': 'kwarg3',
},
)
Example construction and read from test:
.. code-block:: python
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_traceback == True
log_call.log_result_obj == True
On object change, variable types is validated.
In special cases, when special processing required for parameters logging (hide or change parameters in log),
it can be done by override pre_process_param
and post_process_param
.
See API documentation for details.
This is specified helper for making human-readable repr on complex objects. Signature is self-documenting:
.. code-block:: python
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
)
This is specified helper for making human-readable str on complex objects. Signature is self-documenting:
.. code-block:: python
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
)
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 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:
.. code-block:: python
def __init__(
self,
max_indent=20, # maximum allowed indent level
indent_step=4, # step between indents
)
Callable object (PrettyFormat
instance) signature:
.. code-block:: python
def __call__(
self,
src, # object for repr
indent=0, # start indent
no_indent_start=False # do not indent the first level
)
pretty_repr behavior could be overridden for your classes by implementing specific magic method:
.. code-block:: python
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.
.. code-block:: python
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.
This special case of property is useful in cases, where a lot of properties should be logged by similar way without writing a lot of code.
Basic API is conform with property
, but in addition it is possible to customize logger, log levels and log conditions.
Usage examples:
Simple usage. All by default. logger is re-used:
logger
or log
,LOGGER
, log
,logwrap.log_on_access
logger... code-block:: python
import logging
class Target(object):
def init(self, val='ok')
self.val = val
self.logger = logging.get_logger(self.__class__.__name__) # Single for class, follow subclassing
def __repr__(self):
return "{cls}(val={self.val})".format(cls=self.__class__.__name__, self=self)
@logwrap.LogOnAccess
def ok(self):
return self.val
@ok.setter
def ok(self, val):
self.val = val
@ok.deleter
def ok(self):
self.val = ""
2. Use with global logger for class:
.. code-block:: python
class Target(object):
def init(self, val='ok')
self.val = val
def __repr__(self):
return "{cls}(val={self.val})".format(cls=self.__class__.__name__, self=self)
@logwrap.LogOnAccess
def ok(self):
return self.val
@ok.setter
def ok(self, val):
self.val = val
@ok.deleter
def ok(self):
self.val = ""
ok.logger = 'test_logger'
ok.log_level = logging.INFO
ok.exc_level = logging.ERROR
ok.log_object_repr = True # As by default
ok.log_before = True # As by default
ok.log_success = True # As by default
ok.log_failure = True # As by default
ok.log_traceback = True # As by default
ok.override_name = None # As by default: use original name
The main test mechanism for the package logwrap
is using tox
.
Available environments can be collected via tox -l
GitHub: <https://github.com/python-useful-helpers/logwrap/actions>
_ is used for functional tests.
FAQs
Decorator for logging function arguments and return value by human-readable way
We found that logwrap demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.