From 637eca2606c9f5de0673fcff436186f730aff9d2 Mon Sep 17 00:00:00 2001 From: ronen-y Date: Sat, 23 Mar 2019 23:22:12 +0200 Subject: [PATCH 1/5] Now we can wrap function with free variables --- ipdbugger/__init__.py | 17 ++++++++++++++++- setup.py | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ipdbugger/__init__.py b/ipdbugger/__init__.py index 4a5cd5b..7306be8 100644 --- a/ipdbugger/__init__.py +++ b/ipdbugger/__init__.py @@ -301,9 +301,24 @@ def wrapper(*args, **kw): ast.fix_missing_locations(tree) + # Set wrapping function body with all free_vars sets to None + body_list = [ast.parse("{var} = None".format(var=free_var)).body[0] + for free_var in victim.__code__.co_freevars] + + # Add the original function ("victim") to wrapping function body + body_list.append(tree.body[0]) + + # Define the wrapping function object + function_definition = "def _free_vars_wrapper(): pass" + wrapping_function = ast.parse(function_definition).body[0] + wrapping_function.body = body_list + + # Replace original function ("victim") with wrapping function + tree.body[0] = wrapping_function + # Create a new runnable code object to replace the original code code = compile(tree, victim.__code__.co_filename, 'exec') - victim.__code__ = code.co_consts[0] + victim.__code__ = code.co_consts[0].co_consts[-1] # Set a flag to indicate that the method was wrapped victim._ipdebug_wrapped = True diff --git a/setup.py b/setup.py index 1b14fc9..9884975 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ """Setup file for handling packaging and distribution.""" from setuptools import setup -__version__ = "2.1.0" +__version__ = "2.2.0" setup( name="ipdbugger", From c91f355f8015091b1c16392dd79ea07e13d0f911 Mon Sep 17 00:00:00 2001 From: ronen-y Date: Sat, 23 Mar 2019 23:34:19 +0200 Subject: [PATCH 2/5] fix version for ipdb to 0.11 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9884975..2e49bbe 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ author_email="gregoil@walla.co.il", url="https://github.com/gregoil/ipdbugger", keywords="ipdb debug debugger exception", - install_requires=["ipdb", + install_requires=["ipdb==0.11", "future", "colorama", "termcolor"], From 58d0752c344b4a538cd71984910e6f34b3dfe3bc Mon Sep 17 00:00:00 2001 From: ronen-y Date: Sat, 23 Mar 2019 23:43:19 +0200 Subject: [PATCH 3/5] set code object of victim to right value --- ipdbugger/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipdbugger/__init__.py b/ipdbugger/__init__.py index 7306be8..931c375 100644 --- a/ipdbugger/__init__.py +++ b/ipdbugger/__init__.py @@ -318,7 +318,7 @@ def wrapper(*args, **kw): # Create a new runnable code object to replace the original code code = compile(tree, victim.__code__.co_filename, 'exec') - victim.__code__ = code.co_consts[0].co_consts[-1] + victim.__code__ = code.co_consts[0].co_consts[1] # Set a flag to indicate that the method was wrapped victim._ipdebug_wrapped = True From 69a65aaae24e1207b96f8bdb13c6511bbf38f668 Mon Sep 17 00:00:00 2001 From: ronen-y Date: Wed, 3 Apr 2019 15:57:45 +0300 Subject: [PATCH 4/5] fix by review --- ipdbugger/__init__.py | 21 ++++++++++----------- setup.py | 2 +- tests/test_debug.py | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/ipdbugger/__init__.py b/ipdbugger/__init__.py index 931c375..3af396d 100644 --- a/ipdbugger/__init__.py +++ b/ipdbugger/__init__.py @@ -99,10 +99,9 @@ def start_debugging(): # Get the frame with the error. test_frame = sys._getframe(-1).f_back - from ipdb.__main__ import wrap_sys_excepthook, def_colors + from ipdb.__main__ import wrap_sys_excepthook wrap_sys_excepthook() - IPDBugger(exc_info=sys.exc_info(), - color_scheme=def_colors).set_trace(test_frame) + IPDBugger(exc_info=sys.exc_info()).set_trace(test_frame) class ErrorsCatchTransformer(ast.NodeTransformer): @@ -163,8 +162,7 @@ def try_except_handler(self, node): self.exception_handlers, new_exception_handlers # Run recursively on all sub nodes with the new ignore list - for item in node.body: - self.visit(item) + super(ErrorsCatchTransformer, self).generic_visit(node) # Revert changes from ignore list self.exception_handlers = old_exception_handlers @@ -301,19 +299,20 @@ def wrapper(*args, **kw): ast.fix_missing_locations(tree) - # Set wrapping function body with all free_vars sets to None + # Define the wrapping function object + function_definition = "def _free_vars_wrapper(): pass" + wrapping_function = ast.parse(function_definition).body[0] + + # Initialize closure's variables to None body_list = [ast.parse("{var} = None".format(var=free_var)).body[0] for free_var in victim.__code__.co_freevars] - # Add the original function ("victim") to wrapping function body + # Add the original function ("victim") to the wrapping function body_list.append(tree.body[0]) - # Define the wrapping function object - function_definition = "def _free_vars_wrapper(): pass" - wrapping_function = ast.parse(function_definition).body[0] wrapping_function.body = body_list - # Replace original function ("victim") with wrapping function + # Replace original function ("victim") with the wrapping function tree.body[0] = wrapping_function # Create a new runnable code object to replace the original code diff --git a/setup.py b/setup.py index 2e49bbe..9884975 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ author_email="gregoil@walla.co.il", url="https://github.com/gregoil/ipdbugger", keywords="ipdb debug debugger exception", - install_requires=["ipdb==0.11", + install_requires=["ipdb", "future", "colorama", "termcolor"], diff --git a/tests/test_debug.py b/tests/test_debug.py index 2eda261..5e15267 100644 --- a/tests/test_debug.py +++ b/tests/test_debug.py @@ -210,3 +210,17 @@ def func(): pass func() + + +def test_wrapping_function_with_closure(): + """Test wrapping function with closure""" + raise_exc = True + + @debug + def func(): + if raise_exc: + raise ValueError() + + with capture_output(), patch('bdb.Bdb.set_trace') as set_trace: + func() + assert set_trace.called_once From eedfa03a987cb2303b2389279303eb4c605ef260 Mon Sep 17 00:00:00 2001 From: ronen-y Date: Thu, 4 Apr 2019 08:48:21 +0300 Subject: [PATCH 5/5] fix cases of try statement with else --- ipdbugger/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipdbugger/__init__.py b/ipdbugger/__init__.py index 3af396d..fe47715 100644 --- a/ipdbugger/__init__.py +++ b/ipdbugger/__init__.py @@ -162,7 +162,7 @@ def try_except_handler(self, node): self.exception_handlers, new_exception_handlers # Run recursively on all sub nodes with the new ignore list - super(ErrorsCatchTransformer, self).generic_visit(node) + node.body = [self.visit(node_item) for node_item in node.body] # Revert changes from ignore list self.exception_handlers = old_exception_handlers