From b9f35dbcb243dd486c0150d4b7fa6b8ba064ce47 Mon Sep 17 00:00:00 2001 From: Elijah Qi Date: Sat, 15 Apr 2023 22:11:25 -0400 Subject: [PATCH 1/5] Modify depth to depth_iterator to support float('inf') and also break if _frame_candidate is internal_frame --- pysnooper/tracer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pysnooper/tracer.py b/pysnooper/tracer.py index 0f35500..9c075ed 100644 --- a/pysnooper/tracer.py +++ b/pysnooper/tracer.py @@ -403,10 +403,13 @@ def trace(self, frame, event, arg): return None else: _frame_candidate = frame - for i in range(1, self.depth): + depth_iterator = itertools.count(1) if (self.depth == float('inf')) else range(1, self.depth) + for i in depth_iterator: _frame_candidate = _frame_candidate.f_back if _frame_candidate is None: return None + elif self._is_internal_frame(_frame_candidate): + return None elif _frame_candidate.f_code in self.target_codes or _frame_candidate in self.target_frames: break else: From 24a83765dd4e6eb7f184ab6ff93a62c2398ac022 Mon Sep 17 00:00:00 2001 From: Elijah Qi Date: Sat, 15 Apr 2023 22:22:08 -0400 Subject: [PATCH 2/5] Title: Replace deprecated getName() method with name attribute Body: This commit resolves a DeprecationWarning in the tracer.py file. The deprecated getName() method, which is used to get the name of the current_thread object, has been replaced with the recommended name attribute. Changes: - Updated line 473 in tracer.py to use current_thread.name instead of current_thread.getName() With this change, the deprecation warning will no longer appear when running tests, and the code will be compatible with future releases of Python that may remove the deprecated method. --- a.py | 9 +++++++++ pysnooper/tracer.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 a.py diff --git a/a.py b/a.py new file mode 100644 index 0000000..c3cdd29 --- /dev/null +++ b/a.py @@ -0,0 +1,9 @@ +import pysnooper + +@pysnooper.snoop(depth = float('inf')) +def func(x): + if x == 0: + return + func(x - 1) + +func(3) \ No newline at end of file diff --git a/pysnooper/tracer.py b/pysnooper/tracer.py index 9c075ed..64e2d4b 100644 --- a/pysnooper/tracer.py +++ b/pysnooper/tracer.py @@ -470,7 +470,7 @@ def trace(self, frame, event, arg): "thread_info") current_thread = threading.current_thread() thread_info = "{ident}-{name} ".format( - ident=current_thread.ident, name=current_thread.getName()) + ident=current_thread.ident, name=current_thread.name) thread_info = self.set_thread_info_padding(thread_info) ### Reporting newish and modified variables: ########################## From 93eecf679e236c39b04a29ad9d4d9522ced9d68b Mon Sep 17 00:00:00 2001 From: AndreaYanglq <97621027+AndreaYanglq@users.noreply.github.com> Date: Sat, 15 Apr 2023 22:57:04 -0400 Subject: [PATCH 3/5] add test_depth_inf --- .DS_Store | Bin 0 -> 6148 bytes tests/test_depth_inf/__init__.py | 0 tests/test_depth_inf/factorial.py | 13 ++++++ tests/test_depth_inf/test_depth_inf.py | 59 +++++++++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 .DS_Store create mode 100644 tests/test_depth_inf/__init__.py create mode 100644 tests/test_depth_inf/factorial.py create mode 100644 tests/test_depth_inf/test_depth_inf.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..835a6b7eff91ecd3069a57f1dee80cbb762e33fa GIT binary patch literal 6148 zcmeHKy-ve05I(m-3LsF24s7HJ5PgGy!V~ZSl>VqiB27fgz?O|yU|@q6U}i%Mzy<>g zVrGK{cD}PsYpbDRLI~YezAyFN*qDFI?`Qp51(0Z}{=f z%y`~+-VF=uD5WLLo6`}Es7pim9ct4qTA#We6RMog&UU$7UA$i28g4VjPqPWzpH+DL zsmc5UN}<}2+8*1=bLz%iZoBsnCu7}gt;?h=?#)}}X=z@oHlzV%_~lUVz+*r!o$@S~ z%Ts-@dS`Sh8P8=kJJaK*^t#TCS9Iv{s=meG_Jp1u(W)7(@?D OJ_NK3;zWU8Rp1lve!eFF literal 0 HcmV?d00001 diff --git a/tests/test_depth_inf/__init__.py b/tests/test_depth_inf/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_depth_inf/factorial.py b/tests/test_depth_inf/factorial.py new file mode 100644 index 0000000..e7539d3 --- /dev/null +++ b/tests/test_depth_inf/factorial.py @@ -0,0 +1,13 @@ +#!/usr/bin/python3 +import pysnooper +# test recursion +@pysnooper.snoop(depth=float("inf"), color = False) +def factorial(x): + """This is a recursive function + to find the factorial of an integer""" + + if x == 1: + return 1 + else: + return (x * factorial(x-1)) + diff --git a/tests/test_depth_inf/test_depth_inf.py b/tests/test_depth_inf/test_depth_inf.py new file mode 100644 index 0000000..c8e904b --- /dev/null +++ b/tests/test_depth_inf/test_depth_inf.py @@ -0,0 +1,59 @@ +# Copyright 2019 Ram Rachum and collaborators. +# This program is distributed under the MIT license. + +import io +import textwrap +import threading +import types +import os +import sys + +from pysnooper.utils import truncate +import pytest + +import pysnooper +from pysnooper.variables import needs_parentheses +from ..utils import (assert_output, assert_sample_output, VariableEntry, + CallEntry, LineEntry, ReturnEntry, OpcodeEntry, + ReturnValueEntry, ExceptionEntry, ExceptionValueEntry, + SourcePathEntry, CallEndedByExceptionEntry, + ElapsedTimeEntry) +from .. import mini_toolbox +from . import factorial + + +def test_multiple_files(): + with mini_toolbox.OutputCapturer(stdout=False, + stderr=True) as output_capturer: + result = factorial.factorial(3) + assert result == 6 + output = output_capturer.string_io.getvalue() + assert_output( + output, + ( + SourcePathEntry(source_path_regex=r'.*factorial\.py$'), + VariableEntry('x', '3'), + CallEntry(), + LineEntry(), + LineEntry(), + VariableEntry('x', '2'), + CallEntry(), + LineEntry(), + LineEntry(), + VariableEntry('x', '1'), + CallEntry(), + LineEntry(), + LineEntry(), + ReturnEntry(), + ReturnValueEntry('1'), + ElapsedTimeEntry(), + ReturnEntry(), + ReturnValueEntry('2'), + ElapsedTimeEntry(), + ReturnEntry(), + ReturnValueEntry('6'), + ElapsedTimeEntry() + ) + ) + + From c84286c1897c6e35367c7053810522ea715437af Mon Sep 17 00:00:00 2001 From: Elijah Qi Date: Sat, 15 Apr 2023 23:00:13 -0400 Subject: [PATCH 4/5] test_infinite_depth_support.py --- a.py | 9 --- tests/test_infinite_depth_support.py | 113 +++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 9 deletions(-) delete mode 100644 a.py create mode 100644 tests/test_infinite_depth_support.py diff --git a/a.py b/a.py deleted file mode 100644 index c3cdd29..0000000 --- a/a.py +++ /dev/null @@ -1,9 +0,0 @@ -import pysnooper - -@pysnooper.snoop(depth = float('inf')) -def func(x): - if x == 0: - return - func(x - 1) - -func(3) \ No newline at end of file diff --git a/tests/test_infinite_depth_support.py b/tests/test_infinite_depth_support.py new file mode 100644 index 0000000..1e76151 --- /dev/null +++ b/tests/test_infinite_depth_support.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Elijah Qi and Liuqing Yang. +# This program is distributed under the MIT license. + +import io +import textwrap +import threading +import types +import sys + +from pysnooper.utils import truncate +import pytest + +import pysnooper +from pysnooper import pycompat +from pysnooper.variables import needs_parentheses +from .utils import (assert_output, assert_sample_output, VariableEntry, + CallEntry, LineEntry, ReturnEntry, OpcodeEntry, + ReturnValueEntry, ExceptionEntry, ExceptionValueEntry, + SourcePathEntry, CallEndedByExceptionEntry, + ElapsedTimeEntry) +from . import mini_toolbox + +@pytest.mark.parametrize("normalize", (True, False)) +def test_var_order(normalize): + string_io = io.StringIO() + + def func1(x): + return x + + def func(x): + func1(x) + + def foo(x): + func(x) + + def recursive_function(x): + if x == 0: + return 1 + + foo(x) + + recursive_function(x - 1) + + with pysnooper.snoop(string_io, depth=float('inf'), normalize=normalize, color=False): + recursive_function(1) + + output = string_io.getvalue() + with open('test_var_order.txt', 'w') as f: + f.write(output) + + assert_output( + output, + ( + SourcePathEntry(), + VariableEntry(), + VariableEntry(), + VariableEntry(), + VariableEntry(), + VariableEntry(), + VariableEntry(), + LineEntry("recursive_function(1)"), + VariableEntry("x", "1"), + VariableEntry("foo"), + VariableEntry("recursive_function"), + + CallEntry("def recursive_function(x):"), + LineEntry("if x == 0:"), + LineEntry(), + LineEntry("foo(x)"), + + VariableEntry("x", "1"), + VariableEntry("func1"), + CallEntry("def func(x):"), + LineEntry("func1(x)"), + + VariableEntry("x", "1"), + VariableEntry("func1"), + CallEntry("def func(x):"), + LineEntry("func1(x)"), + + VariableEntry("x", "1"), + CallEntry("def func1(x):"), + LineEntry("return x"), + ReturnEntry(), + ReturnValueEntry("1"), + + ReturnEntry(), + ReturnValueEntry("None"), + + ReturnEntry(), + ReturnValueEntry("None"), + + LineEntry("recursive_function(x - 1)"), + + VariableEntry("x", "0"), + VariableEntry("foo"), + VariableEntry("recursive_function"), + + CallEntry("def recursive_function(x):"), + LineEntry("if x == 0:"), + LineEntry("return 1"), + ReturnEntry(), + ReturnValueEntry("1"), + + ReturnEntry(), + ReturnValueEntry("None"), + + LineEntry("with pysnooper.snoop(string_io, depth=float('inf'), normalize=normalize, color=False):"), + ElapsedTimeEntry(), + ), + normalize=normalize, + ) From 70f69a5cb771b75a81ac648ef7ab1838ccd0eb01 Mon Sep 17 00:00:00 2001 From: Elijah Qi Date: Sat, 15 Apr 2023 23:46:27 -0400 Subject: [PATCH 5/5] Add infinite depth support for function call tracing This commit adds a new feature that enables infinite depth support for function call tracing in pysnooper. The test_infinite_depth_support test case has been added to verify the correct behavior of the feature. The test case covers the case of tracing a recursive function call with unlimited depth and checks the output against the expected values. The feature works by setting the depth parameter to float('inf') in the pysnooper.snoop function. --- tests/test_depth_inf/test_depth_inf.py | 3 ++- tests/test_infinite_depth_support.py | 11 ++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/test_depth_inf/test_depth_inf.py b/tests/test_depth_inf/test_depth_inf.py index c8e904b..7f30d2a 100644 --- a/tests/test_depth_inf/test_depth_inf.py +++ b/tests/test_depth_inf/test_depth_inf.py @@ -1,4 +1,5 @@ -# Copyright 2019 Ram Rachum and collaborators. +# -*- coding: utf-8 -*- +# Copyright 2023 Elijah Qi and Liuqing Yang. # This program is distributed under the MIT license. import io diff --git a/tests/test_infinite_depth_support.py b/tests/test_infinite_depth_support.py index 1e76151..b5e0148 100644 --- a/tests/test_infinite_depth_support.py +++ b/tests/test_infinite_depth_support.py @@ -22,7 +22,7 @@ from . import mini_toolbox @pytest.mark.parametrize("normalize", (True, False)) -def test_var_order(normalize): +def test_infinite_depth_support(normalize): string_io = io.StringIO() def func1(x): @@ -46,8 +46,6 @@ def recursive_function(x): recursive_function(1) output = string_io.getvalue() - with open('test_var_order.txt', 'w') as f: - f.write(output) assert_output( output, @@ -66,13 +64,12 @@ def recursive_function(x): CallEntry("def recursive_function(x):"), LineEntry("if x == 0:"), - LineEntry(), LineEntry("foo(x)"), VariableEntry("x", "1"), - VariableEntry("func1"), - CallEntry("def func(x):"), - LineEntry("func1(x)"), + VariableEntry("func"), + CallEntry("def foo(x):"), + LineEntry("func(x)"), VariableEntry("x", "1"), VariableEntry("func1"),