This commit is contained in:
Colin 2024-10-12 23:38:54 +08:00 committed by GitHub
commit 810f994e09
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -156,6 +156,14 @@ def get_write_function(output, overwrite):
return write
def _path_eq_or_sub(c, p):
# ref: https://stackoverflow.com/q/3812849/12388699
# assert file == os.path.realpath(file), 'property of frame.f_code.co_filename'
p_slash = os.path.join(p, '')
return c.rstrip(os.sep) == p.rstrip(os.sep) or \
os.path.commonprefix([c, p_slash]).rstrip(os.sep) == p.rstrip(os.sep)
class FileWriter(object):
def __init__(self, path, overwrite):
self.path = pycompat.text_type(path)
@ -200,6 +208,10 @@ class Tracer:
Show snoop lines for functions that your function calls::
@pysnooper.snoop(depth=2)
Only snoop lines that are in the specified source directories::
@pysnooper.snoop(src_dir='path/to/myproj')
Start all snoop lines with a prefix, to grep for them easily::
@ -234,7 +246,7 @@ class Tracer:
def __init__(self, output=None, watch=(), watch_explode=(), depth=1,
prefix='', overwrite=False, thread_info=False, custom_repr=(),
max_variable_length=100, normalize=False, relative_time=False,
color=True):
color=True, source_paths=[], exclude_paths=[]):
self._write = get_write_function(output, overwrite)
self.watch = [
@ -264,7 +276,6 @@ class Tracer:
self.relative_time = relative_time
self.color = color and sys.platform in ('linux', 'linux2', 'cygwin',
'darwin')
if self.color:
self._FOREGROUND_BLUE = '\x1b[34m'
self._FOREGROUND_CYAN = '\x1b[36m'
@ -290,6 +301,18 @@ class Tracer:
self._STYLE_NORMAL = ''
self._STYLE_RESET_ALL = ''
def process_paths(paths):
ret = []
if isinstance(paths, str):
ret = [paths]
else:
assert isinstance(paths, list)
ret = paths
return list(map(os.path.realpath, ret))
self.source_paths = process_paths(source_paths)
self.exclude_paths = process_paths(exclude_paths)
def __call__(self, function_or_class):
if DISABLED:
return function_or_class
@ -406,6 +429,17 @@ class Tracer:
# 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 self.source_paths and not (
frame.f_code.co_filename[0] == '/' and # in case of '<frozen xxx>'
any(_path_eq_or_sub(frame.f_code.co_filename, p) for p in self.source_paths)
):
return None
if self.exclude_paths and (
frame.f_code.co_filename[0] == '/' and # in case of '<frozen xxx>'
any(_path_eq_or_sub(frame.f_code.co_filename, p) for p in self.exclude_paths)
):
return None
if not (frame.f_code in self.target_codes or frame in self.target_frames):
if self.depth == 1: