mirror of
https://github.com/cool-RR/PySnooper.git
synced 2026-01-23 02:14:04 +00:00
Remove trailing whitespace
This commit is contained in:
parent
28a8b24494
commit
e898561a4f
9 changed files with 73 additions and 76 deletions
|
|
@ -1,13 +1,13 @@
|
|||
dist: xenial
|
||||
language: python
|
||||
python:
|
||||
#- pypy2.7
|
||||
- 2.7
|
||||
- 3.4
|
||||
- 3.5
|
||||
- 3.6
|
||||
- 3.7
|
||||
- 3.8-dev
|
||||
- pypy2.7
|
||||
- pypy3.5
|
||||
|
||||
env:
|
||||
|
|
|
|||
20
README.md
20
README.md
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
[](https://travis-ci.org/cool-RR/PySnooper)
|
||||
|
||||
**PySnooper** is a poor man's debugger.
|
||||
**PySnooper** is a poor man's debugger.
|
||||
|
||||
You're trying to figure out why your Python code isn't doing what you think it should be doing. You'd love to use a full-fledged debugger with breakpoints and watches, but you can't be bothered to set one up right now.
|
||||
|
||||
You're looking at a section of Python code. You want to know which lines are running and which aren't, and what the values of the local variables are.
|
||||
You're looking at a section of Python code. You want to know which lines are running and which aren't, and what the values of the local variables are.
|
||||
|
||||
Most people would use a `print` line. Probably several of them, in strategic locations, some of them showing the values of variables. Then they'd use the output of the prints to figure out which code ran when and what was in the variables.
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ What makes **PySnooper** stand out from all other code intelligence tools? You c
|
|||
We're writing a function that converts a number to binary, by returing a list of bits. Let's snoop on it by adding the `@pysnooper.snoop()` decorator:
|
||||
|
||||
import pysnooper
|
||||
|
||||
|
||||
@pysnooper.snoop()
|
||||
def number_to_bits(number):
|
||||
if number:
|
||||
|
|
@ -32,11 +32,11 @@ We're writing a function that converts a number to binary, by returing a list of
|
|||
return bits
|
||||
else:
|
||||
return [0]
|
||||
|
||||
|
||||
number_to_bits(6)
|
||||
|
||||
The output to stderr is:
|
||||
|
||||
The output to stderr is:
|
||||
|
||||
Starting var:.. number = 6
|
||||
21:14:32.099769 call 3 @pysnooper.snoop()
|
||||
21:14:32.099769 line 5 if number:
|
||||
|
|
@ -69,13 +69,13 @@ The output to stderr is:
|
|||
If stderr is not easily accessible for you, you can redirect the output to a file easily:
|
||||
|
||||
@pysnooper.snoop('/my/log/file.log')
|
||||
|
||||
|
||||
Want to see values of some variables that aren't local variables?
|
||||
|
||||
@pysnooper.snoop(variables=('foo.bar', 'self.whatever'))
|
||||
|
||||
|
||||
# Installation #
|
||||
|
||||
|
||||
# Installation #
|
||||
|
||||
Use `pip`:
|
||||
|
||||
|
|
|
|||
|
|
@ -14,20 +14,19 @@ else:
|
|||
"""
|
||||
__metaclass__ = abc.ABCMeta
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
|
||||
if hasattr(os, 'PathLike'):
|
||||
PathLike = os.PathLike
|
||||
else:
|
||||
class PathLike(ABC):
|
||||
"""Abstract base class for implementing the file system path protocol."""
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def __fspath__(self):
|
||||
"""Return the file system path representation of the object."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@classmethod
|
||||
def __subclasshook__(cls, subclass):
|
||||
return hasattr(subclass, '__fspath__')
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ from . import utils
|
|||
from . import pycompat
|
||||
from .tracer import Tracer
|
||||
|
||||
|
||||
|
||||
def get_write_function(output):
|
||||
if output is None:
|
||||
def write(s):
|
||||
|
|
@ -31,10 +31,10 @@ def get_write_function(output):
|
|||
assert isinstance(output, utils.WritableStream)
|
||||
def write(s):
|
||||
output.write(s)
|
||||
|
||||
|
||||
return write
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def snoop(output=None, variables=(), depth=1, prefix=''):
|
||||
write = get_write_function(output)
|
||||
|
|
@ -45,8 +45,7 @@ def snoop(output=None, variables=(), depth=1, prefix=''):
|
|||
write=write, variables=variables,
|
||||
depth=depth, prefix=prefix):
|
||||
return function(*args, **kwargs)
|
||||
|
||||
|
||||
return decorate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ def get_source_from_frame(frame):
|
|||
pass
|
||||
function = frame.f_code.co_name
|
||||
loader = frame.f_globals.get('__loader__')
|
||||
|
||||
|
||||
source = None
|
||||
if hasattr(loader, 'get_source'):
|
||||
try:
|
||||
|
|
@ -106,7 +106,7 @@ class Tracer:
|
|||
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
|
||||
|
|
@ -119,16 +119,16 @@ class Tracer:
|
|||
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
sys.settrace(self.original_trace_function)
|
||||
|
||||
|
||||
|
||||
def trace(self, frame, event, arg):
|
||||
|
||||
|
||||
### Checking whether we should trace this line: #######################
|
||||
# #
|
||||
# We should trace this line either if it's in the decorated function,
|
||||
# or the user asked to go a few levels deeper and we're within that
|
||||
# number of levels deeper.
|
||||
|
||||
|
||||
if frame.f_code is not self.target_code_object:
|
||||
if self.depth == 1:
|
||||
# We did the most common and quickest check above, because the
|
||||
|
|
@ -150,23 +150,23 @@ class Tracer:
|
|||
indent = ''
|
||||
# #
|
||||
### Finished checking whether we should trace this line. ##############
|
||||
|
||||
|
||||
### Reporting newish and modified variables: ##########################
|
||||
# #
|
||||
self.frame_to_old_local_reprs[frame] = old_local_reprs = \
|
||||
self.frame_to_local_reprs[frame]
|
||||
self.frame_to_local_reprs[frame] = local_reprs = \
|
||||
get_local_reprs(frame, variables=self.variables)
|
||||
|
||||
|
||||
modified_local_reprs = {}
|
||||
newish_local_reprs = {}
|
||||
|
||||
|
||||
for key, value in local_reprs.items():
|
||||
if key not in old_local_reprs:
|
||||
newish_local_reprs[key] = value
|
||||
elif old_local_reprs[key] != value:
|
||||
modified_local_reprs[key] = value
|
||||
|
||||
|
||||
newish_string = ('Starting var:.. ' if event == 'call' else
|
||||
'New var:....... ')
|
||||
for name, value_repr in newish_local_reprs.items():
|
||||
|
|
@ -177,7 +177,7 @@ class Tracer:
|
|||
**locals()))
|
||||
# #
|
||||
### Finished newish and modified variables. ###########################
|
||||
|
||||
|
||||
now_string = datetime_module.datetime.now().time().isoformat()
|
||||
source_line = get_source_from_frame(frame)[frame.f_lineno - 1]
|
||||
self.write('{indent}{now_string} {event:9} '
|
||||
|
|
|
|||
|
|
@ -30,4 +30,3 @@ class WritableStream(ABC):
|
|||
return _check_methods(C, 'write')
|
||||
return NotImplemented
|
||||
|
||||
|
||||
|
|
|
|||
6
setup.py
6
setup.py
|
|
@ -14,8 +14,8 @@ setuptools.setup(
|
|||
long_description_content_type='text/markdown',
|
||||
url='https://github.com/cool-RR/PySnooper',
|
||||
packages=setuptools.find_packages(),
|
||||
install_requires=open('requirements.txt', 'r').read().split('\n'),
|
||||
tests_require=open('test_requirements.txt', 'r').read().split('\n'),
|
||||
install_requires=open('requirements.txt', 'r').read().split('\n'),
|
||||
tests_require=open('test_requirements.txt', 'r').read().split('\n'),
|
||||
classifiers=[
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
|
|
@ -23,5 +23,5 @@ setuptools.setup(
|
|||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: OS Independent',
|
||||
],
|
||||
|
||||
|
||||
)
|
||||
|
|
@ -29,21 +29,21 @@ def test_string_io():
|
|||
(
|
||||
VariableEntry('foo', value_regex="u?'baba'"),
|
||||
CallEntry(),
|
||||
LineEntry('x = 7'),
|
||||
VariableEntry('x', '7'),
|
||||
LineEntry('y = 8'),
|
||||
VariableEntry('y', '8'),
|
||||
LineEntry('return y + x'),
|
||||
ReturnEntry('return y + x'),
|
||||
LineEntry('x = 7'),
|
||||
VariableEntry('x', '7'),
|
||||
LineEntry('y = 8'),
|
||||
VariableEntry('y', '8'),
|
||||
LineEntry('return y + x'),
|
||||
ReturnEntry('return y + x'),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_variables():
|
||||
|
||||
class Foo(object):
|
||||
def __init__(self):
|
||||
self.x = 2
|
||||
|
||||
|
||||
def square(self):
|
||||
self.x **= 2
|
||||
|
||||
|
|
@ -64,42 +64,42 @@ def test_variables():
|
|||
VariableEntry(),
|
||||
VariableEntry(),
|
||||
CallEntry(),
|
||||
LineEntry('foo = Foo()'),
|
||||
LineEntry('foo = Foo()'),
|
||||
VariableEntry(),
|
||||
VariableEntry(),
|
||||
LineEntry(),
|
||||
LineEntry(),
|
||||
VariableEntry('i', '0'),
|
||||
LineEntry(),
|
||||
LineEntry(),
|
||||
VariableEntry('foo.x', '4'),
|
||||
LineEntry(),
|
||||
LineEntry(),
|
||||
VariableEntry('i', '1'),
|
||||
LineEntry(),
|
||||
LineEntry(),
|
||||
VariableEntry('foo.x', '16'),
|
||||
LineEntry(),
|
||||
ReturnEntry(),
|
||||
LineEntry(),
|
||||
ReturnEntry(),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_depth():
|
||||
string_io = io.StringIO()
|
||||
|
||||
|
||||
def f4(x4):
|
||||
result4 = x4 * 2
|
||||
return result4
|
||||
|
||||
|
||||
def f3(x3):
|
||||
result3 = f4(x3)
|
||||
return result3
|
||||
|
||||
|
||||
def f2(x2):
|
||||
result2 = f3(x2)
|
||||
return result2
|
||||
|
||||
|
||||
@pysnooper.snoop(string_io, depth=3)
|
||||
def f1(x1):
|
||||
result1 = f2(x1)
|
||||
return result1
|
||||
|
||||
|
||||
result = f1(10)
|
||||
assert result == 20
|
||||
output = string_io.getvalue()
|
||||
|
|
@ -109,26 +109,26 @@ def test_depth():
|
|||
VariableEntry(),
|
||||
VariableEntry(),
|
||||
CallEntry(),
|
||||
LineEntry(),
|
||||
|
||||
VariableEntry(),
|
||||
VariableEntry(),
|
||||
CallEntry(),
|
||||
LineEntry(),
|
||||
|
||||
LineEntry(),
|
||||
|
||||
VariableEntry(),
|
||||
VariableEntry(),
|
||||
CallEntry(),
|
||||
LineEntry(),
|
||||
|
||||
|
||||
VariableEntry(),
|
||||
VariableEntry(),
|
||||
CallEntry(),
|
||||
LineEntry(),
|
||||
|
||||
VariableEntry(),
|
||||
LineEntry(),
|
||||
ReturnEntry(),
|
||||
|
||||
|
||||
VariableEntry(),
|
||||
LineEntry(),
|
||||
ReturnEntry(),
|
||||
|
||||
|
||||
VariableEntry(),
|
||||
LineEntry(),
|
||||
ReturnEntry(),
|
||||
|
|
@ -141,7 +141,7 @@ 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
|
||||
|
|
@ -161,11 +161,11 @@ def test_method_and_prefix():
|
|||
(
|
||||
VariableEntry(),
|
||||
CallEntry(),
|
||||
LineEntry('foo = 7'),
|
||||
LineEntry('foo = 7'),
|
||||
VariableEntry('foo', '7'),
|
||||
LineEntry('self.x **= 2'),
|
||||
LineEntry(),
|
||||
ReturnEntry(),
|
||||
LineEntry('self.x **= 2'),
|
||||
LineEntry(),
|
||||
ReturnEntry(),
|
||||
),
|
||||
prefix='ZZZ'
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class _BaseEntry(pysnooper.pycompat.ABC):
|
|||
@abc.abstractmethod
|
||||
def check(self, s):
|
||||
pass
|
||||
|
||||
|
||||
class VariableEntry(_BaseEntry):
|
||||
line_pattern = re.compile(
|
||||
r"""^(?P<prefix>.*?)(?P<indent>(?: {4})*)"""
|
||||
|
|
@ -124,7 +124,7 @@ class OpcodeEntry(_BaseEventEntry):
|
|||
|
||||
class OutputFailure(Exception):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def assert_output(output, expected_entries, prefix=None):
|
||||
lines = tuple(filter(None, output.split('\n')))
|
||||
|
|
@ -137,7 +137,7 @@ def assert_output(output, expected_entries, prefix=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