Add support for custom repr

This commit is contained in:
Xiang Gao 2019-05-28 12:53:59 -04:00 committed by Ram Rachum
parent 22019f16ae
commit 4a32e77b33
4 changed files with 60 additions and 7 deletions

View file

@ -143,7 +143,7 @@ Start all snoop lines with a prefix, to grep for them easily:
@pysnooper.snoop(prefix='ZZZ ')
```
On multi-threaded apps identify which thread are snooped in output::
On multi-threaded apps identify which thread are snooped in output:
```python
@pysnooper.snoop(thread_info=True)
@ -151,6 +151,24 @@ On multi-threaded apps identify which thread are snooped in output::
PySnooper supports decorating generators.
You can also customize the repr of an object:
```python
def large(l):
return isinstance(l, list) and len(l) > 5
def print_list_size(l):
return 'list(size={})'.format(len(l))
@pysnooper.snoop(custom_repr=((large, print_list_size),))
def sum_to_x(x):
l = list(range(x))
return sum(l)
sum_to_x(10000)
```
You will get `l = list(size=10000)` for the list
# Installation #

View file

@ -21,11 +21,11 @@ if pycompat.PY2:
ipython_filename_pattern = re.compile('^<ipython-input-([0-9]+)-.*>$')
def get_local_reprs(frame, watch=()):
def get_local_reprs(frame, watch=(), custom_repr=()):
code = frame.f_code
vars_order = code.co_varnames + code.co_cellvars + code.co_freevars + tuple(frame.f_locals.keys())
result_items = [(key, utils.get_shortish_repr(value)) for key, value in frame.f_locals.items()]
result_items = [(key, utils.get_shortish_repr(value, custom_repr=custom_repr)) for key, value in frame.f_locals.items()]
result_items.sort(key=lambda key_value: vars_order.index(key_value[0]))
result = collections.OrderedDict(result_items)
@ -189,6 +189,7 @@ class Tracer:
prefix='',
overwrite=False,
thread_info=False,
custom_repr=(),
):
self._write = get_write_function(output, overwrite)
@ -208,6 +209,7 @@ class Tracer:
self.target_codes = set()
self.target_frames = set()
self.thread_local = threading.local()
self.custom_repr = custom_repr
def __call__(self, function):
self.target_codes.add(function.__code__)
@ -310,7 +312,7 @@ class Tracer:
# #
old_local_reprs = self.frame_to_local_reprs.get(frame, {})
self.frame_to_local_reprs[frame] = local_reprs = \
get_local_reprs(frame, watch=self.watch)
get_local_reprs(frame, watch=self.watch, custom_repr=self.custom_repr)
newish_string = ('Starting var:.. ' if event == 'call' else
'New var:....... ')
@ -383,7 +385,7 @@ class Tracer:
thread_global.depth -= 1
if not ended_by_exception:
return_value_repr = utils.get_shortish_repr(arg)
return_value_repr = utils.get_shortish_repr(arg, custom_repr=self.custom_repr)
self.write('{indent}Return value:.. {return_value_repr}'.
format(**locals()))

View file

@ -49,9 +49,14 @@ def shitcode(s):
)
def get_shortish_repr(item):
def get_shortish_repr(item, custom_repr=()):
try:
r = repr(item)
for condition, action in custom_repr:
if condition(item):
r = action(item)
break
else:
r = repr(item)
except Exception:
r = 'REPR FAILED'
r = r.replace('\r', '').replace('\n', '')

View file

@ -1131,4 +1131,32 @@ def test_generator():
)
def test_custom_repr():
string_io = io.StringIO()
def large(l):
return isinstance(l, list) and len(l) > 5
def print_list_size(l):
return 'list(size={})'.format(len(l))
@pysnooper.snoop(string_io, custom_repr=((large, print_list_size),))
def sum_to_x(x):
l = list(range(x))
return sum(l)
result = sum_to_x(10000)
output = string_io.getvalue()
assert_output(
output,
(
VariableEntry('x', '10000'),
CallEntry(),
LineEntry(),
VariableEntry('l', 'list(size=10000)'),
LineEntry(),
ReturnEntry(),
ReturnValueEntry('49995000'),
)
)