From 81cf41c925c9aa1fe89b29e71492b1363bd69e97 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Mon, 29 Jan 2024 13:06:34 +0000 Subject: [PATCH 01/15] Simplify mocking Signed-off-by: Ahdra Merali --- tests/ipython/test_ipython.py | 45 ++++++++++------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 697a28106c..f33eb55ccd 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -128,9 +128,9 @@ def my_func:, @pytest.fixture -def dummy_pipeline(dummy_node): +def dummy_pipelines(dummy_node): # return a list of pipelines - return {"dummy": modular_pipeline([dummy_node])} + return [modular_pipeline([dummy_node])] class TestLoadKedroObjects: @@ -382,7 +382,7 @@ class MockKedroContext: class TestLoadNodeMagic: - def test_load_node_magic(self, mocker, dummy_function_file_lines, dummy_pipeline): + def test_load_node_magic(self, mocker, dummy_function_file_lines, dummy_pipelines): # Reimport `pipelines` from `kedro.framework.project` to ensure that # it was not removed by prior tests. from kedro.framework.project import pipelines @@ -393,38 +393,17 @@ def test_load_node_magic(self, mocker, dummy_function_file_lines, dummy_pipeline mocker.patch( "builtins.open", mocker.mock_open(read_data=dummy_function_file_lines) ) - pipelines.configure("dummy_pipeline") # Setup the pipelines - my_pipelines = dummy_pipeline - - def my_register_pipeline(): - return my_pipelines - - mocker.patch.object( - pipelines, - "_get_pipelines_registry_callable", - return_value=my_register_pipeline, - ) + mocker.patch.object(pipelines, "values", return_value=dummy_pipelines) node_to_load = "dummy_node" magic_load_node(node_to_load) - def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipeline): + def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): # wraps all the other functions mocker.patch( "builtins.open", mocker.mock_open(read_data=dummy_function_file_lines) ) - pipelines.configure("dummy_pipeline") # Setup the pipelines - - my_pipelines = dummy_pipeline - - def my_register_pipeline(): - return my_pipelines - - mocker.patch.object( - pipelines, - "_get_pipelines_registry_callable", - return_value=my_register_pipeline, - ) + mocker.patch.object(pipelines, "values", return_value=dummy_pipelines) node_inputs = """# Prepare necessary inputs for debugging dummy_input = catalog.load("dummy_input") @@ -455,17 +434,17 @@ def my_register_pipeline(): for cell, expected_cell in zip(cells_list, expected_cells): assert cell == expected_cell - def test_find_node(self, mocker, dummy_pipeline, dummy_node): - mocker.patch.object(pipelines, "values", return_value=dummy_pipeline) + def test_find_node(self, dummy_pipelines, dummy_node): node_to_find = "dummy_node" - result = _find_node(node_to_find, dummy_pipeline) + dummy_registered_pipelines = {"my_pipeline": dummy_pipelines[0]} + result = _find_node(node_to_find, dummy_registered_pipelines) assert result == dummy_node - def test_node_not_found(self, mocker, dummy_pipeline): - mocker.patch.object(pipelines, "values", return_value=dummy_pipeline) + def test_node_not_found(self, dummy_pipelines): node_to_find = "not_a_node" + dummy_registered_pipelines = {"my_pipeline": dummy_pipelines[0]} with pytest.raises(ValueError) as excinfo: - _find_node(node_to_find, dummy_pipeline) + _find_node(node_to_find, dummy_registered_pipelines) assert f"Node with name='{node_to_find}' not found in any pipelines." in str( excinfo.value From 07d254b1bea71251ba1077f4ca54f47f36fc3206 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Mon, 29 Jan 2024 13:24:23 +0000 Subject: [PATCH 02/15] Check node func names Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 8 ++++++++ tests/ipython/test_ipython.py | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index 28f3696345..1dfcfc3381 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -249,6 +249,14 @@ def _find_node(node_name: str, pipelines: _ProjectPipelines) -> Node: return found_node except ValueError: continue + + # Try looking at node func names instead? + for pipeline in pipelines.values(): + for node in pipeline.nodes: + if node.func.__name__ == node_name: + found_func_node: Node = node + return found_func_node + # If reached the node was not found in the project raise ValueError(f"Node with name='{node_name}' not found in any pipelines.") diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index f33eb55ccd..7f1f428863 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -434,12 +434,18 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): for cell, expected_cell in zip(cells_list, expected_cells): assert cell == expected_cell - def test_find_node(self, dummy_pipelines, dummy_node): + def test_find_node_by_node_name(self, dummy_pipelines, dummy_node): node_to_find = "dummy_node" dummy_registered_pipelines = {"my_pipeline": dummy_pipelines[0]} result = _find_node(node_to_find, dummy_registered_pipelines) assert result == dummy_node + def test_find_node_by_func_name(self, dummy_pipelines, dummy_node): + node_to_find = "dummy_function" + dummy_registered_pipelines = {"my_pipeline": dummy_pipelines[0]} + result = _find_node(node_to_find, dummy_registered_pipelines) + assert result == dummy_node + def test_node_not_found(self, dummy_pipelines): node_to_find = "not_a_node" dummy_registered_pipelines = {"my_pipeline": dummy_pipelines[0]} From 21a28f0de7bd84d9a30495f484029730a8996550 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Mon, 29 Jan 2024 14:48:10 +0000 Subject: [PATCH 03/15] Naive fix for return statements Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 25 ++++++++++++++++++++++--- tests/ipython/test_ipython.py | 9 ++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index 1dfcfc3381..2e3eb249f9 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -301,12 +301,31 @@ def _prepare_function_body(func: Callable) -> str: # https://stackoverflow.com/questions/38050649/getting-a-python-functions-source-code-without-the-definition-lines all_source_lines = inspect.getsourcelines(func)[0] # Remove any decorators - func_lines = dropwhile(lambda x: x.startswith("@"), all_source_lines) - line: str = next(func_lines).strip() + raw_func_lines = dropwhile(lambda x: x.startswith("@"), all_source_lines) + line: str = next(raw_func_lines).strip() if not line.startswith("def "): return line.rsplit(",")[0].strip() # Handle functions that are not one-liners - first_line = next(func_lines) + first_line = next(raw_func_lines) + + # Convert return statements into print statements + func_lines = [] + for line in raw_func_lines: + if line.lstrip().startswith("return"): + return_statement = line.lstrip() + line_indentation = len(line) - len(return_statement) + commented_return = line[:line_indentation] + "# " + return_statement + printed_return = ( + line[:line_indentation] + + "print(" + + return_statement[len("return") :].strip() + + ")" + ) + func_lines.append(commented_return) + func_lines.append(printed_return) + else: + func_lines.append(line) + # Find the indentation of the first line indentation = len(first_line) - len(first_line.lstrip()) body = "".join( diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 7f1f428863..5609ad74cb 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -420,7 +420,8 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): # this is an in-line comment in the body of the function random_assignment = "Added for a longer function" random_assignment += "make sure to modify variable" -return not dummy_input""" +# return not dummy_input +print(not dummy_input)""" expected_cells = [ node_inputs, @@ -492,7 +493,8 @@ def test_prepare_function_body(self): # this is an in-line comment in the body of the function random_assignment = "Added for a longer function" random_assignment += "make sure to modify variable" -return not dummy_input""" +# return not dummy_input +print(not dummy_input)""" result = _prepare_function_body(dummy_function) assert result == func_strings @@ -515,7 +517,8 @@ def test_get_nested_function_body(self): def test_get_function_with_loop_body(self): func_strings = """for x in dummy_list: continue -return len(dummy_list)""" +# return len(dummy_list) +print(len(dummy_list))""" result = _prepare_function_body(dummy_function_with_loop) assert result == func_strings From 6e382a2a5b67260e9a52748cdc8b4e96d0ad4fe2 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Mon, 29 Jan 2024 14:57:43 +0000 Subject: [PATCH 04/15] Handle nested case Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 2 +- tests/ipython/test_ipython.py | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index 2e3eb249f9..a273ac4c22 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -319,7 +319,7 @@ def _prepare_function_body(func: Callable) -> str: line[:line_indentation] + "print(" + return_statement[len("return") :].strip() - + ")" + + ")\n" ) func_lines.append(commented_return) func_lines.append(printed_return) diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 5609ad74cb..cf32d89c8f 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -503,16 +503,15 @@ def test_get_lambda_function_body(self, lambda_node): result = _prepare_function_body(lambda_node.func) assert result == "func=lambda x: x" - @pytest.mark.skip(reason="Not supported yet") def test_get_nested_function_body(self): - func_strings = [ - "def nested_function(input):", - "\nreturn not input", - "\nreturn nested_function(dummy_input)\n", - ] + func_strings = """def nested_function(input): + # return not input + print(not input) +# return nested_function(dummy_input) +print(nested_function(dummy_input))""" + result = _prepare_function_body(dummy_nested_function) - assert result == "".join(func_strings) - # TODO fix - fails because skips nested function definition + assert result == func_strings def test_get_function_with_loop_body(self): func_strings = """for x in dummy_list: From 2f15f86ae2280d3a00fbe325251990ee428404c3 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Mon, 29 Jan 2024 18:44:13 +0000 Subject: [PATCH 05/15] Change pipelines fixture type Signed-off-by: Ahdra Merali --- tests/ipython/test_ipython.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index cf32d89c8f..daa2c66f74 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -129,8 +129,8 @@ def my_func:, @pytest.fixture def dummy_pipelines(dummy_node): - # return a list of pipelines - return [modular_pipeline([dummy_node])] + # return a dict of pipelines + return {"dummy_pipeline": modular_pipeline([dummy_node])} class TestLoadKedroObjects: @@ -393,7 +393,8 @@ def test_load_node_magic(self, mocker, dummy_function_file_lines, dummy_pipeline mocker.patch( "builtins.open", mocker.mock_open(read_data=dummy_function_file_lines) ) - mocker.patch.object(pipelines, "values", return_value=dummy_pipelines) + mock_pipeline_values = dummy_pipelines.values() + mocker.patch.object(pipelines, "values", return_value=mock_pipeline_values) node_to_load = "dummy_node" magic_load_node(node_to_load) @@ -403,7 +404,8 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): mocker.patch( "builtins.open", mocker.mock_open(read_data=dummy_function_file_lines) ) - mocker.patch.object(pipelines, "values", return_value=dummy_pipelines) + mock_pipeline_values = dummy_pipelines.values() + mocker.patch.object(pipelines, "values", return_value=mock_pipeline_values) node_inputs = """# Prepare necessary inputs for debugging dummy_input = catalog.load("dummy_input") @@ -437,19 +439,17 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): def test_find_node_by_node_name(self, dummy_pipelines, dummy_node): node_to_find = "dummy_node" - dummy_registered_pipelines = {"my_pipeline": dummy_pipelines[0]} - result = _find_node(node_to_find, dummy_registered_pipelines) + result = _find_node(node_to_find, dummy_pipelines) assert result == dummy_node def test_find_node_by_func_name(self, dummy_pipelines, dummy_node): node_to_find = "dummy_function" - dummy_registered_pipelines = {"my_pipeline": dummy_pipelines[0]} - result = _find_node(node_to_find, dummy_registered_pipelines) + result = _find_node(node_to_find, dummy_pipelines) assert result == dummy_node def test_node_not_found(self, dummy_pipelines): node_to_find = "not_a_node" - dummy_registered_pipelines = {"my_pipeline": dummy_pipelines[0]} + dummy_registered_pipelines = dummy_pipelines with pytest.raises(ValueError) as excinfo: _find_node(node_to_find, dummy_registered_pipelines) From 28d2ef3b5dcddba77f1f018def1d74b0a7432d9c Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Mon, 29 Jan 2024 19:19:45 +0000 Subject: [PATCH 06/15] Remove unnecessary TODO Signed-off-by: Ahdra Merali --- tests/ipython/test_ipython.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index daa2c66f74..af4291f815 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -479,7 +479,6 @@ def test_prepare_imports_func_not_found(self, mocker): assert f"Could not find {dummy_function.__name__}" in str(excinfo.value) def test_prepare_node_inputs(self, dummy_node): - # TODO Ahdra check - does this address parameters properly? func_inputs = """# Prepare necessary inputs for debugging dummy_input = catalog.load("dummy_input") my_input = catalog.load("extra_input")""" From 8f57b010a7e7d54973fda9c5410880a7782fead1 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 07:48:21 +0000 Subject: [PATCH 07/15] Revert "Check node func names" This reverts commit 63ee194f5fd955c7a5f31f69dbc716b30d5b67e6. Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 8 -------- tests/ipython/test_ipython.py | 7 +------ 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index a273ac4c22..ef3f0871bb 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -249,14 +249,6 @@ def _find_node(node_name: str, pipelines: _ProjectPipelines) -> Node: return found_node except ValueError: continue - - # Try looking at node func names instead? - for pipeline in pipelines.values(): - for node in pipeline.nodes: - if node.func.__name__ == node_name: - found_func_node: Node = node - return found_func_node - # If reached the node was not found in the project raise ValueError(f"Node with name='{node_name}' not found in any pipelines.") diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index af4291f815..32f08dab08 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -437,16 +437,11 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): for cell, expected_cell in zip(cells_list, expected_cells): assert cell == expected_cell - def test_find_node_by_node_name(self, dummy_pipelines, dummy_node): + def test_find_node(self, dummy_pipelines, dummy_node): node_to_find = "dummy_node" result = _find_node(node_to_find, dummy_pipelines) assert result == dummy_node - def test_find_node_by_func_name(self, dummy_pipelines, dummy_node): - node_to_find = "dummy_function" - result = _find_node(node_to_find, dummy_pipelines) - assert result == dummy_node - def test_node_not_found(self, dummy_pipelines): node_to_find = "not_a_node" dummy_registered_pipelines = dummy_pipelines From 66fb218992cef0f0870f3a9a0021ce307deb4e6b Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 07:53:26 +0000 Subject: [PATCH 08/15] Replace commented return statements with a display() statement Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 2 +- tests/ipython/test_ipython.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index ef3f0871bb..ab4869f6c9 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -309,7 +309,7 @@ def _prepare_function_body(func: Callable) -> str: commented_return = line[:line_indentation] + "# " + return_statement printed_return = ( line[:line_indentation] - + "print(" + + "display(" + return_statement[len("return") :].strip() + ")\n" ) diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 32f08dab08..47441ab4f5 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -423,7 +423,7 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): random_assignment = "Added for a longer function" random_assignment += "make sure to modify variable" # return not dummy_input -print(not dummy_input)""" +display(not dummy_input)""" expected_cells = [ node_inputs, @@ -488,7 +488,7 @@ def test_prepare_function_body(self): random_assignment = "Added for a longer function" random_assignment += "make sure to modify variable" # return not dummy_input -print(not dummy_input)""" +display(not dummy_input)""" result = _prepare_function_body(dummy_function) assert result == func_strings @@ -500,9 +500,9 @@ def test_get_lambda_function_body(self, lambda_node): def test_get_nested_function_body(self): func_strings = """def nested_function(input): # return not input - print(not input) + display(not input) # return nested_function(dummy_input) -print(nested_function(dummy_input))""" +display(nested_function(dummy_input))""" result = _prepare_function_body(dummy_nested_function) assert result == func_strings @@ -511,7 +511,7 @@ def test_get_function_with_loop_body(self): func_strings = """for x in dummy_list: continue # return len(dummy_list) -print(len(dummy_list))""" +display(len(dummy_list))""" result = _prepare_function_body(dummy_function_with_loop) assert result == func_strings From 3b4562b5d3d36e7a1ecbe1c4850bb58c0995886c Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 07:57:00 +0000 Subject: [PATCH 09/15] Add warning about node name when node not found Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 4 +++- tests/ipython/test_ipython.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index ab4869f6c9..6df91556d6 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -250,7 +250,9 @@ def _find_node(node_name: str, pipelines: _ProjectPipelines) -> Node: except ValueError: continue # If reached the node was not found in the project - raise ValueError(f"Node with name='{node_name}' not found in any pipelines.") + raise ValueError( + f"Node with name='{node_name}' not found in any pipelines. Remember to specify the node name, not the node function." + ) def _prepare_imports(node_func: Callable) -> str: diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 47441ab4f5..721435de73 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -448,8 +448,9 @@ def test_node_not_found(self, dummy_pipelines): with pytest.raises(ValueError) as excinfo: _find_node(node_to_find, dummy_registered_pipelines) - assert f"Node with name='{node_to_find}' not found in any pipelines." in str( - excinfo.value + assert ( + f"Node with name='{node_to_find}' not found in any pipelines. Remember to specify the node name, not the node function." + in str(excinfo.value) ) def test_prepare_imports(self, mocker, dummy_function_file_lines): From 839220e11f9349b57d205a54c797ec00185291e6 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 08:02:53 +0000 Subject: [PATCH 10/15] Add line about debugging inputs in catalog Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 5 ++++- tests/ipython/test_ipython.py | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index 6df91556d6..45ef7e6e33 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -282,7 +282,10 @@ def _prepare_node_inputs(node: Node) -> str: node_inputs = node.inputs func_params = list(signature.parameters) - statements = ["# Prepare necessary inputs for debugging"] + statements = [ + "# Prepare necessary inputs for debugging", + "# All debugging inputs must be specified in your project catalog", + ] for node_input, func_param in zip(node_inputs, func_params): statements.append(f'{func_param} = catalog.load("{node_input}")') diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 721435de73..ec4a55bb51 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -408,6 +408,7 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): mocker.patch.object(pipelines, "values", return_value=mock_pipeline_values) node_inputs = """# Prepare necessary inputs for debugging +# All debugging inputs must be specified in your project catalog dummy_input = catalog.load("dummy_input") my_input = catalog.load("extra_input")""" @@ -476,6 +477,7 @@ def test_prepare_imports_func_not_found(self, mocker): def test_prepare_node_inputs(self, dummy_node): func_inputs = """# Prepare necessary inputs for debugging +# All debugging inputs must be specified in your project catalog dummy_input = catalog.load("dummy_input") my_input = catalog.load("extra_input")""" From fda5f0020d22ec9a67f174086e5c86fe67c27b80 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 08:03:19 +0000 Subject: [PATCH 11/15] Lint Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index 45ef7e6e33..9330fa83e5 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -285,7 +285,7 @@ def _prepare_node_inputs(node: Node) -> str: statements = [ "# Prepare necessary inputs for debugging", "# All debugging inputs must be specified in your project catalog", - ] + ] for node_input, func_param in zip(node_inputs, func_params): statements.append(f'{func_param} = catalog.load("{node_input}")') From e9d3d4b18a9eee71b3a1c5aff9ce82ff50cf9b85 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 08:04:48 +0000 Subject: [PATCH 12/15] Change wording Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 2 +- tests/ipython/test_ipython.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index 9330fa83e5..3de7bc9e93 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -284,7 +284,7 @@ def _prepare_node_inputs(node: Node) -> str: statements = [ "# Prepare necessary inputs for debugging", - "# All debugging inputs must be specified in your project catalog", + "# All debugging inputs must be defined in your project catalog", ] for node_input, func_param in zip(node_inputs, func_params): diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index ec4a55bb51..14d1391182 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -408,7 +408,7 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): mocker.patch.object(pipelines, "values", return_value=mock_pipeline_values) node_inputs = """# Prepare necessary inputs for debugging -# All debugging inputs must be specified in your project catalog +# All debugging inputs must be defined in your project catalog dummy_input = catalog.load("dummy_input") my_input = catalog.load("extra_input")""" @@ -477,7 +477,7 @@ def test_prepare_imports_func_not_found(self, mocker): def test_prepare_node_inputs(self, dummy_node): func_inputs = """# Prepare necessary inputs for debugging -# All debugging inputs must be specified in your project catalog +# All debugging inputs must be defined in your project catalog dummy_input = catalog.load("dummy_input") my_input = catalog.load("extra_input")""" From 7c694bf5af4a59aa3343702a220642bebf1ed762 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 08:14:48 +0000 Subject: [PATCH 13/15] Revert "Replace commented return statements with a display() statement" This reverts commit ad63afcfc00eb25b98608fe6fb5b4158a60a426a. Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 2 +- tests/ipython/test_ipython.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index 3de7bc9e93..14371cc583 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -314,7 +314,7 @@ def _prepare_function_body(func: Callable) -> str: commented_return = line[:line_indentation] + "# " + return_statement printed_return = ( line[:line_indentation] - + "display(" + + "print(" + return_statement[len("return") :].strip() + ")\n" ) diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 14d1391182..91bd25d7c6 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -424,7 +424,7 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): random_assignment = "Added for a longer function" random_assignment += "make sure to modify variable" # return not dummy_input -display(not dummy_input)""" +print(not dummy_input)""" expected_cells = [ node_inputs, @@ -491,7 +491,7 @@ def test_prepare_function_body(self): random_assignment = "Added for a longer function" random_assignment += "make sure to modify variable" # return not dummy_input -display(not dummy_input)""" +print(not dummy_input)""" result = _prepare_function_body(dummy_function) assert result == func_strings @@ -503,9 +503,9 @@ def test_get_lambda_function_body(self, lambda_node): def test_get_nested_function_body(self): func_strings = """def nested_function(input): # return not input - display(not input) + print(not input) # return nested_function(dummy_input) -display(nested_function(dummy_input))""" +print(nested_function(dummy_input))""" result = _prepare_function_body(dummy_nested_function) assert result == func_strings @@ -514,7 +514,7 @@ def test_get_function_with_loop_body(self): func_strings = """for x in dummy_list: continue # return len(dummy_list) -display(len(dummy_list))""" +print(len(dummy_list))""" result = _prepare_function_body(dummy_function_with_loop) assert result == func_strings From 1bbd161a26fa41dd1fad4f3308eb7a8bde23c908 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 08:17:55 +0000 Subject: [PATCH 14/15] Revert "Naive fix for return statements" This reverts commit 04c022e9d8ac4f36d484a35acfb9dce53635eba3. Signed-off-by: Ahdra Merali --- kedro/ipython/__init__.py | 25 +++---------------------- tests/ipython/test_ipython.py | 9 +++------ 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/kedro/ipython/__init__.py b/kedro/ipython/__init__.py index 14371cc583..9289050a15 100644 --- a/kedro/ipython/__init__.py +++ b/kedro/ipython/__init__.py @@ -298,31 +298,12 @@ def _prepare_function_body(func: Callable) -> str: # https://stackoverflow.com/questions/38050649/getting-a-python-functions-source-code-without-the-definition-lines all_source_lines = inspect.getsourcelines(func)[0] # Remove any decorators - raw_func_lines = dropwhile(lambda x: x.startswith("@"), all_source_lines) - line: str = next(raw_func_lines).strip() + func_lines = dropwhile(lambda x: x.startswith("@"), all_source_lines) + line: str = next(func_lines).strip() if not line.startswith("def "): return line.rsplit(",")[0].strip() # Handle functions that are not one-liners - first_line = next(raw_func_lines) - - # Convert return statements into print statements - func_lines = [] - for line in raw_func_lines: - if line.lstrip().startswith("return"): - return_statement = line.lstrip() - line_indentation = len(line) - len(return_statement) - commented_return = line[:line_indentation] + "# " + return_statement - printed_return = ( - line[:line_indentation] - + "print(" - + return_statement[len("return") :].strip() - + ")\n" - ) - func_lines.append(commented_return) - func_lines.append(printed_return) - else: - func_lines.append(line) - + first_line = next(func_lines) # Find the indentation of the first line indentation = len(first_line) - len(first_line.lstrip()) body = "".join( diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 91bd25d7c6..3de635c819 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -423,8 +423,7 @@ def test_load_node(self, mocker, dummy_function_file_lines, dummy_pipelines): # this is an in-line comment in the body of the function random_assignment = "Added for a longer function" random_assignment += "make sure to modify variable" -# return not dummy_input -print(not dummy_input)""" +return not dummy_input""" expected_cells = [ node_inputs, @@ -490,8 +489,7 @@ def test_prepare_function_body(self): # this is an in-line comment in the body of the function random_assignment = "Added for a longer function" random_assignment += "make sure to modify variable" -# return not dummy_input -print(not dummy_input)""" +return not dummy_input""" result = _prepare_function_body(dummy_function) assert result == func_strings @@ -513,8 +511,7 @@ def test_get_nested_function_body(self): def test_get_function_with_loop_body(self): func_strings = """for x in dummy_list: continue -# return len(dummy_list) -print(len(dummy_list))""" +return len(dummy_list)""" result = _prepare_function_body(dummy_function_with_loop) assert result == func_strings From 4581373d696f6d8e34128752aab4fee2feabee37 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 1 Feb 2024 08:26:27 +0000 Subject: [PATCH 15/15] Update tests Signed-off-by: Ahdra Merali --- tests/ipython/test_ipython.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/ipython/test_ipython.py b/tests/ipython/test_ipython.py index 3de635c819..0a0ad98527 100644 --- a/tests/ipython/test_ipython.py +++ b/tests/ipython/test_ipython.py @@ -500,10 +500,8 @@ def test_get_lambda_function_body(self, lambda_node): def test_get_nested_function_body(self): func_strings = """def nested_function(input): - # return not input - print(not input) -# return nested_function(dummy_input) -print(nested_function(dummy_input))""" + return not input +return nested_function(dummy_input)""" result = _prepare_function_body(dummy_nested_function) assert result == func_strings