mirror of
https://github.com/cool-RR/PySnooper.git
synced 2026-07-20 17:59:34 +00:00
Add prefix feature
This commit is contained in:
parent
621a4865cc
commit
28a8b24494
5 changed files with 84 additions and 44 deletions
50
README.md
50
README.md
|
|
@ -37,31 +37,31 @@ We're writing a function that converts a number to binary, by returing a list of
|
|||
|
||||
The output to stderr is:
|
||||
|
||||
............... number = 6
|
||||
00:24:15.284000 call 3 @pysnooper.snoop()
|
||||
00:24:15.284000 line 5 if number:
|
||||
00:24:15.284000 line 6 bits = []
|
||||
............... bits = []
|
||||
00:24:15.284000 line 7 while number:
|
||||
00:24:15.284000 line 8 number, remainder = divmod(number, 2)
|
||||
............... number = 3
|
||||
............... remainder = 0
|
||||
00:24:15.284000 line 9 bits.insert(0, remainder)
|
||||
............... bits = [0]
|
||||
00:24:15.284000 line 7 while number:
|
||||
00:24:15.284000 line 8 number, remainder = divmod(number, 2)
|
||||
............... number = 1
|
||||
............... remainder = 1
|
||||
00:24:15.284000 line 9 bits.insert(0, remainder)
|
||||
............... bits = [1, 0]
|
||||
00:24:15.284000 line 7 while number:
|
||||
00:24:15.284000 line 8 number, remainder = divmod(number, 2)
|
||||
............... number = 0
|
||||
00:24:15.284000 line 9 bits.insert(0, remainder)
|
||||
............... bits = [1, 1, 0]
|
||||
00:24:15.284000 line 7 while number:
|
||||
00:24:15.284000 line 10 return bits
|
||||
00:24:15.284000 return 10 return bits
|
||||
Starting var:.. number = 6
|
||||
21:14:32.099769 call 3 @pysnooper.snoop()
|
||||
21:14:32.099769 line 5 if number:
|
||||
21:14:32.099769 line 6 bits = []
|
||||
New var:....... bits = []
|
||||
21:14:32.099769 line 7 while number:
|
||||
21:14:32.099769 line 8 number, remainder = divmod(number, 2)
|
||||
New var:....... remainder = 0
|
||||
Modified var:.. number = 3
|
||||
21:14:32.099769 line 9 bits.insert(0, remainder)
|
||||
Modified var:.. bits = [0]
|
||||
21:14:32.099769 line 7 while number:
|
||||
21:14:32.099769 line 8 number, remainder = divmod(number, 2)
|
||||
Modified var:.. number = 1
|
||||
Modified var:.. remainder = 1
|
||||
21:14:32.099769 line 9 bits.insert(0, remainder)
|
||||
Modified var:.. bits = [1, 0]
|
||||
21:14:32.099769 line 7 while number:
|
||||
21:14:32.099769 line 8 number, remainder = divmod(number, 2)
|
||||
Modified var:.. number = 0
|
||||
21:14:32.099769 line 9 bits.insert(0, remainder)
|
||||
Modified var:.. bits = [1, 1, 0]
|
||||
21:14:32.099769 line 7 while number:
|
||||
21:14:32.099769 line 10 return bits
|
||||
21:14:32.099769 return 10 return bits
|
||||
|
||||
|
||||
# Features #
|
||||
|
|
|
|||
|
|
@ -21,38 +21,29 @@ from .tracer import Tracer
|
|||
def get_write_function(output):
|
||||
if output is None:
|
||||
def write(s):
|
||||
s += '\n'
|
||||
if isinstance(s, bytes): # Python 2 compatibility
|
||||
s = s.decode('utf-8')
|
||||
stderr = sys.stderr
|
||||
stderr.write(s)
|
||||
elif isinstance(output, (pycompat.PathLike, str)):
|
||||
def write(s):
|
||||
s += '\n'
|
||||
if isinstance(s, bytes): # Python 2 compatibility
|
||||
s = s.decode('utf-8')
|
||||
with open(output_path, 'a') as output_file:
|
||||
output_file.write(s)
|
||||
else:
|
||||
assert isinstance(output, utils.WritableStream)
|
||||
def write(s):
|
||||
s += '\n'
|
||||
if isinstance(s, bytes): # Python 2 compatibility
|
||||
s = s.decode('utf-8')
|
||||
output.write(s)
|
||||
|
||||
return write
|
||||
|
||||
|
||||
|
||||
def snoop(output=None, variables=(), depth=1):
|
||||
def snoop(output=None, variables=(), depth=1, prefix=''):
|
||||
write = get_write_function(output)
|
||||
@decorator.decorator
|
||||
def decorate(function, *args, **kwargs):
|
||||
target_code_object = function.__code__
|
||||
with Tracer(target_code_object=target_code_object,
|
||||
write=write, variables=variables,
|
||||
depth=depth):
|
||||
depth=depth, prefix=prefix):
|
||||
return function(*args, **kwargs)
|
||||
|
||||
return decorate
|
||||
|
|
|
|||
|
|
@ -96,14 +96,22 @@ def get_source_from_frame(frame):
|
|||
return source
|
||||
|
||||
class Tracer:
|
||||
def __init__(self, target_code_object, write, variables=(), depth=1):
|
||||
def __init__(self, target_code_object, write, variables=(), depth=1,
|
||||
prefix=''):
|
||||
self.target_code_object = target_code_object
|
||||
self.write = write
|
||||
self._write = write
|
||||
self.variables = variables
|
||||
self.frame_to_old_local_reprs = collections.defaultdict(lambda: {})
|
||||
self.frame_to_local_reprs = collections.defaultdict(lambda: {})
|
||||
self.depth = depth
|
||||
self.prefix = prefix
|
||||
assert self.depth >= 1
|
||||
|
||||
def write(self, s):
|
||||
s = '{self.prefix}{s}\n'.format(**locals())
|
||||
if isinstance(s, bytes): # Python 2 compatibility
|
||||
s = s.decode()
|
||||
self._write(s)
|
||||
|
||||
def __enter__(self):
|
||||
self.original_trace_function = sys.gettrace()
|
||||
|
|
|
|||
|
|
@ -135,3 +135,37 @@ def test_depth():
|
|||
)
|
||||
)
|
||||
|
||||
|
||||
def test_method_and_prefix():
|
||||
|
||||
class Baz(object):
|
||||
def __init__(self):
|
||||
self.x = 2
|
||||
|
||||
@pysnooper.snoop(variables=('self.x'), prefix='ZZZ')
|
||||
def square(self):
|
||||
foo = 7
|
||||
self.x **= 2
|
||||
return self
|
||||
|
||||
baz = Baz()
|
||||
|
||||
with sys_tools.OutputCapturer(stdout=False,
|
||||
stderr=True) as output_capturer:
|
||||
result = baz.square()
|
||||
assert result is baz
|
||||
assert result.x == 4
|
||||
output = output_capturer.string_io.getvalue()
|
||||
assert_output(
|
||||
output,
|
||||
(
|
||||
VariableEntry(),
|
||||
CallEntry(),
|
||||
LineEntry('foo = 7'),
|
||||
VariableEntry('foo', '7'),
|
||||
LineEntry('self.x **= 2'),
|
||||
LineEntry(),
|
||||
ReturnEntry(),
|
||||
),
|
||||
prefix='ZZZ'
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ class _BaseEntry(pysnooper.pycompat.ABC):
|
|||
|
||||
class VariableEntry(_BaseEntry):
|
||||
line_pattern = re.compile(
|
||||
r"""^(?P<indent>(?: {4})*)(?P<stage>New|Modified|Starting) var:"""
|
||||
r"""^(?P<prefix>.*?)(?P<indent>(?: {4})*)"""
|
||||
r"""(?P<stage>New|Modified|Starting) var:"""
|
||||
r"""\.{2,7} (?P<name>[^ ]+) = (?P<value>.+)$"""
|
||||
)
|
||||
def __init__(self, name=None, value=None, stage=None,
|
||||
|
|
@ -62,7 +63,7 @@ class VariableEntry(_BaseEntry):
|
|||
match = self.line_pattern.match(s)
|
||||
if not match:
|
||||
return False
|
||||
indent, stage, name, value = match.groups()
|
||||
_, _, stage, name, value = match.groups()
|
||||
return (self._check_name(name) and self._check_value(value) and
|
||||
self._check_stage(stage))
|
||||
|
||||
|
|
@ -79,8 +80,9 @@ class _BaseEventEntry(_BaseEntry):
|
|||
re.compile(source_regex))
|
||||
|
||||
line_pattern = re.compile(
|
||||
(r"""^(?P<indent>(?: {4})*)[0-9:.]{15} (?P<event_name>[a-z]*) +"""
|
||||
r"""(?P<line_number>[0-9]*) +(?P<source>.*)$""")
|
||||
(r"""^(?P<prefix>.*?)(?P<indent>(?: {4})*)[0-9:.]{15} """
|
||||
r"""(?P<event_name>[a-z]*) +(?P<line_number>[0-9]*) """
|
||||
r"""+(?P<source>.*)$""")
|
||||
)
|
||||
|
||||
@caching.CachedProperty
|
||||
|
|
@ -99,7 +101,7 @@ class _BaseEventEntry(_BaseEntry):
|
|||
match = self.line_pattern.match(s)
|
||||
if not match:
|
||||
return False
|
||||
indent, event_name, _, source = match.groups()
|
||||
_, _, event_name, _, source = match.groups()
|
||||
return event_name == self.event_name and self._check_source(source)
|
||||
|
||||
|
||||
|
|
@ -124,13 +126,18 @@ class OutputFailure(Exception):
|
|||
pass
|
||||
|
||||
|
||||
def assert_output(output, expected_entries):
|
||||
def assert_output(output, expected_entries, prefix=None):
|
||||
lines = tuple(filter(None, output.split('\n')))
|
||||
if len(lines) != len(expected_entries):
|
||||
raise OutputFailure(
|
||||
'Output has {len(lines)} lines, while we expect '
|
||||
'{len(expected_entries)} lines.'.format(**locals())
|
||||
)
|
||||
if prefix is not None:
|
||||
for line in lines:
|
||||
if not line.startswith(prefix):
|
||||
raise OutputFailure(line)
|
||||
|
||||
for expected_entry, line in zip(expected_entries, lines):
|
||||
if not expected_entry.check(line):
|
||||
raise OutputFailure(line)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue