Skip to content

Commit 87ddd23

Browse files
committed
Allow blacklisting of argument names
The main reason for blacklisting - security requirements, when sensitive data should be excluded from log without corruption. Signed-off-by: Alexey Stepanov <penguinolog@gmail.com>
1 parent f532df5 commit 87ddd23

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
CHANGELOG
22
=========
3+
Version 1.3.0
4+
-------------
5+
* Allowed to blacklist call arguments
6+
37
Version 1.2.0
48
-------------
59
* Fix dict keys length calculation

README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Argumented usage with arguments from signature:
6262
exc_level=logging.ERROR,
6363
max_indent=20, # forwarded to the pretty_repr
6464
spec=None, # use target callable function for spec
65+
blacklisted_names=None, # list argument names, which should be dropped from log
6566
)
6667
6768
Usage examples:

logwrap/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from ._repr_utils import pretty_repr
3030
from ._repr_utils import pretty_str
3131

32-
__version__ = '1.2.0'
32+
__version__ = '1.3.0'
3333

3434
__all__ = [
3535
'logwrap',

logwrap/_log_wrap.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@
4949
comment = "\n{spc:<{indent}}# {{kind!s}}:".format(spc='', indent=indent).format
5050

5151

52-
def _get_func_args_repr(sig, args, kwargs, max_indent):
52+
def _get_func_args_repr(sig, args, kwargs, max_indent, blacklisted_names):
5353
"""Internal helper for reducing complexity of decorator code
5454
5555
:type sig: inspect.Signature
5656
:type max_indent: int
57+
:type blacklisted_names: list
5758
:rtype: str
5859
"""
5960

@@ -63,6 +64,9 @@ def _get_func_args_repr(sig, args, kwargs, max_indent):
6364

6465
last_kind = None
6566
for param in sig.parameters.values():
67+
if param.name in blacklisted_names:
68+
continue
69+
6670
if last_kind != param.kind:
6771
param_str += comment(kind=param.kind)
6872
last_kind = param.kind
@@ -81,11 +85,12 @@ def _get_func_args_repr(sig, args, kwargs, max_indent):
8185

8286

8387
def logwrap(
84-
log=_logger,
85-
log_level=logging.DEBUG,
86-
exc_level=logging.ERROR,
87-
max_indent=20,
88-
spec=None,
88+
log=_logger,
89+
log_level=logging.DEBUG,
90+
exc_level=logging.ERROR,
91+
max_indent=20,
92+
spec=None,
93+
blacklisted_names=None,
8994
):
9095
"""Log function calls and return values
9196
@@ -104,9 +109,15 @@ def logwrap(
104109
Note: this object should provide fully compatible signature
105110
with decorated function, or arguments bind will be failed!
106111
:type spec: callable
112+
:param blacklisted_names: Blacklisted argument names.
113+
Arguments with this names will be skipped in log.
114+
:type blacklisted_names: list
107115
:return: built real decorator
108116
:rtype: callable
109117
"""
118+
if blacklisted_names is None:
119+
blacklisted_names = []
120+
110121
def real_decorator(func):
111122
"""Log function calls and return values
112123
@@ -131,6 +142,7 @@ def wrapped(*args, **kwargs):
131142
args=args,
132143
kwargs=kwargs,
133144
max_indent=max_indent,
145+
blacklisted_names=blacklisted_names
134146
)
135147

136148
log.log(

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
setuptools.setup(
2727
name='logwrap',
2828
version=logwrap.__version__,
29-
packages=['logwrap'],
29+
packages=setuptools.find_packages(),
3030
classifiers=[
3131
'Development Status :: 5 - Production/Stable',
3232

test/test_log_wrap.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,3 +470,39 @@ def func(arg, darg=1, *args, **kwargs):
470470
" }),\n"
471471
"))")
472472
))
473+
474+
def test_args_blacklist(self, logger):
475+
new_logger = mock.Mock(spec=logging.Logger, name='logger')
476+
log = mock.Mock(name='log')
477+
new_logger.attach_mock(log, 'log')
478+
479+
arg1 = 'test arg 1'
480+
arg2 = 'test arg 2'
481+
482+
@logwrap.logwrap(log=new_logger, blacklisted_names=['test_arg2'])
483+
def func(test_arg1, test_arg2):
484+
return test_arg1, test_arg2
485+
486+
result = func(arg1, arg2)
487+
self.assertEqual(result, (arg1, arg2))
488+
log.assert_has_calls((
489+
mock.call(
490+
level=logging.DEBUG,
491+
msg="Calling: \n"
492+
"'func'(\n"
493+
" # POSITIONAL_OR_KEYWORD:\n"
494+
" 'test_arg1'={},\n"
495+
")".format(
496+
logwrap.pretty_repr(
497+
arg1,
498+
indent=8,
499+
no_indent_start=True
500+
)
501+
)
502+
),
503+
mock.call(
504+
level=logging.DEBUG,
505+
msg="Done: 'func' with result:\n{}".format(
506+
logwrap.pretty_repr(result))
507+
),
508+
))

0 commit comments

Comments
 (0)