From c3f8edaa6394e509157147daf686aec6a563ff2d Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Fri, 14 Jul 2023 09:52:16 +0100 Subject: [PATCH 01/17] Add new command Signed-off-by: Ahdra Merali --- kedro/framework/cli/catalog.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kedro/framework/cli/catalog.py b/kedro/framework/cli/catalog.py index 2d74b8d4b3..8d758c7461 100644 --- a/kedro/framework/cli/catalog.py +++ b/kedro/framework/cli/catalog.py @@ -179,6 +179,18 @@ def create_catalog(metadata: ProjectMetadata, pipeline_name, env): click.echo("All datasets are already configured.") +@catalog.command("factories") +@env_option +@click.pass_obj +def list_patterns(metadata: ProjectMetadata, env): + "Show all factory patterns in catalog, ranked by priority by which they are matched" + session = _create_session(metadata.package_name, env=env) + context = session.load_context() + + catalog_factories = context.catalog._dataset_patterns + click.echo(yaml.dump(list(catalog_factories.keys()))) + + def _add_missing_datasets_to_catalog(missing_ds, catalog_path): if catalog_path.is_file(): catalog_config = yaml.safe_load(catalog_path.read_text()) or {} From a3eeed6b76b9e8708b07474a3e71acb8b8f06996 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Fri, 14 Jul 2023 11:14:21 +0100 Subject: [PATCH 02/17] Add test Signed-off-by: Ahdra Merali --- tests/framework/cli/test_catalog.py | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index ca5d4a7a55..07dd20f1ab 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -42,6 +42,17 @@ def fake_catalog_config(): return config +@pytest.fixture +def fake_catalog_with_factories(): + config = { + "some_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + "a_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + "b_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + "other_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + } + return config + + @pytest.mark.usefixtures( "chdir_to_dummy_project", "fake_load_context", "mock_pipelines" ) @@ -360,3 +371,33 @@ def test_bad_env(self, fake_project_cli, fake_metadata): assert result.exit_code assert "Unable to instantiate Kedro session" in result.output + + +@pytest.mark.usefixtures( + "chdir_to_dummy_project", "fake_load_context", "mock_pipelines" +) +def test_list_catalog_factories( + fake_project_cli, + fake_metadata, + mocker, + fake_load_context, + fake_catalog_with_factories, +): + yaml_dump_mock = mocker.patch("yaml.dump", return_value="Result YAML") + mocked_context = fake_load_context.return_value + mocked_context.catalog = DataCatalog.from_config(fake_catalog_with_factories) + + result = CliRunner().invoke( + fake_project_cli, ["catalog", "factories"], obj=fake_metadata + ) + assert not result.exit_code + + expected_patterns_sorted = [ + "other_{placeholder}", + "some_{placeholder}", + "a_{placeholder}", + "b_{placeholder}", + ] + + assert yaml_dump_mock.call_count == 1 + assert yaml_dump_mock.call_args[0][0] == expected_patterns_sorted From 1b96ca9cf47d59bf72429e0531d49a62014a792f Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Fri, 14 Jul 2023 11:15:17 +0100 Subject: [PATCH 03/17] Add changes to RELEASE.md Signed-off-by: Ahdra Merali --- RELEASE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE.md b/RELEASE.md index 00cbffeb90..0dfa1da9fd 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -13,6 +13,7 @@ ## Major features and improvements * Added dataset factories feature which uses pattern matching to reduce the number of catalog entries. * Activated all built-in resolvers by default for `OmegaConfigLoader` except for `oc.env`. +* Added `kedro catalog factories` CLI command. ## Bug fixes and other changes * Updated `kedro catalog list` to work with dataset factories. From 180f32af9beaacfbdae0abbd538e792174f199b6 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Fri, 14 Jul 2023 11:28:38 +0100 Subject: [PATCH 04/17] Change test to better illustrate use case Signed-off-by: Ahdra Merali --- tests/framework/cli/test_catalog.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index 07dd20f1ab..e108dd7ac1 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -45,10 +45,10 @@ def fake_catalog_config(): @pytest.fixture def fake_catalog_with_factories(): config = { - "some_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, - "a_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, - "b_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, - "other_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + "an_example_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + "an_example_{place}_{holder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + "on_{example_placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + "an_{example_placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, } return config @@ -393,10 +393,10 @@ def test_list_catalog_factories( assert not result.exit_code expected_patterns_sorted = [ - "other_{placeholder}", - "some_{placeholder}", - "a_{placeholder}", - "b_{placeholder}", + "an_example_{place}_{holder}", + "an_example_{placeholder}", + "an_{example_placeholder}", + "on_{example_placeholder}", ] assert yaml_dump_mock.call_count == 1 From 27bd40a4eec7f31cf255f725b340d5b06194c612 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Fri, 14 Jul 2023 11:38:58 +0100 Subject: [PATCH 05/17] Lint Signed-off-by: Ahdra Merali --- tests/framework/cli/test_catalog.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index e108dd7ac1..92ce155006 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -45,10 +45,22 @@ def fake_catalog_config(): @pytest.fixture def fake_catalog_with_factories(): config = { - "an_example_{placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, - "an_example_{place}_{holder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, - "on_{example_placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, - "an_{example_placeholder}": {"type": "dummy_type", "filepath": "dummy_filepath"}, + "an_example_{placeholder}": { + "type": "dummy_type", + "filepath": "dummy_filepath", + }, + "an_example_{place}_{holder}": { + "type": "dummy_type", + "filepath": "dummy_filepath", + }, + "on_{example_placeholder}": { + "type": "dummy_type", + "filepath": "dummy_filepath", + }, + "an_{example_placeholder}": { + "type": "dummy_type", + "filepath": "dummy_filepath", + }, } return config From 458fe253544481046ed7398326c59590c5fa9f1e Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Fri, 14 Jul 2023 11:43:46 +0100 Subject: [PATCH 06/17] Update fixture name to be more self-explanatory Signed-off-by: Ahdra Merali --- tests/framework/cli/test_catalog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index 92ce155006..6fbd371cc7 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -43,7 +43,7 @@ def fake_catalog_config(): @pytest.fixture -def fake_catalog_with_factories(): +def fake_catalog_with_overlapping_factories(): config = { "an_example_{placeholder}": { "type": "dummy_type", @@ -393,11 +393,11 @@ def test_list_catalog_factories( fake_metadata, mocker, fake_load_context, - fake_catalog_with_factories, + fake_catalog_with_overlapping_factories, ): yaml_dump_mock = mocker.patch("yaml.dump", return_value="Result YAML") mocked_context = fake_load_context.return_value - mocked_context.catalog = DataCatalog.from_config(fake_catalog_with_factories) + mocked_context.catalog = DataCatalog.from_config(fake_catalog_with_overlapping_factories) result = CliRunner().invoke( fake_project_cli, ["catalog", "factories"], obj=fake_metadata From 1315a312048a42c15954e091d86551d8d642dd32 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Fri, 14 Jul 2023 11:54:24 +0100 Subject: [PATCH 07/17] Lint pt2 Signed-off-by: Ahdra Merali --- tests/framework/cli/test_catalog.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index 6fbd371cc7..13df5dee4e 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -397,7 +397,9 @@ def test_list_catalog_factories( ): yaml_dump_mock = mocker.patch("yaml.dump", return_value="Result YAML") mocked_context = fake_load_context.return_value - mocked_context.catalog = DataCatalog.from_config(fake_catalog_with_overlapping_factories) + mocked_context.catalog = DataCatalog.from_config( + fake_catalog_with_overlapping_factories + ) result = CliRunner().invoke( fake_project_cli, ["catalog", "factories"], obj=fake_metadata From 4aa5bf870d1737e1e9cd18bdfd6a90ef30913742 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Wed, 19 Jul 2023 09:49:32 +0100 Subject: [PATCH 08/17] Add suggestions from code review Signed-off-by: Ahdra Merali --- kedro/framework/cli/catalog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kedro/framework/cli/catalog.py b/kedro/framework/cli/catalog.py index 8d758c7461..3a12381e75 100644 --- a/kedro/framework/cli/catalog.py +++ b/kedro/framework/cli/catalog.py @@ -183,7 +183,7 @@ def create_catalog(metadata: ProjectMetadata, pipeline_name, env): @env_option @click.pass_obj def list_patterns(metadata: ProjectMetadata, env): - "Show all factory patterns in catalog, ranked by priority by which they are matched" + "Show all factory patterns in the catalog, ranked by priority by which they are matched." session = _create_session(metadata.package_name, env=env) context = session.load_context() From 9c817be227ec6b2cb0ac5bf33d1ab867f40393d5 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Wed, 19 Jul 2023 09:52:21 +0100 Subject: [PATCH 09/17] Change command name Signed-off-by: Ahdra Merali --- kedro/framework/cli/catalog.py | 2 +- tests/framework/cli/test_catalog.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kedro/framework/cli/catalog.py b/kedro/framework/cli/catalog.py index 3a12381e75..c0e5d584fa 100644 --- a/kedro/framework/cli/catalog.py +++ b/kedro/framework/cli/catalog.py @@ -179,7 +179,7 @@ def create_catalog(metadata: ProjectMetadata, pipeline_name, env): click.echo("All datasets are already configured.") -@catalog.command("factories") +@catalog.command("factory list") @env_option @click.pass_obj def list_patterns(metadata: ProjectMetadata, env): diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index 13df5dee4e..692ba04386 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -402,7 +402,7 @@ def test_list_catalog_factories( ) result = CliRunner().invoke( - fake_project_cli, ["catalog", "factories"], obj=fake_metadata + fake_project_cli, ["catalog", "factory list"], obj=fake_metadata ) assert not result.exit_code From d1f9e64c25cddde76cc5f3c0e7a213f6778f2d39 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Wed, 19 Jul 2023 10:20:05 +0100 Subject: [PATCH 10/17] Add explicit dataset to test case Signed-off-by: Ahdra Merali --- tests/framework/cli/test_catalog.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index 692ba04386..880828e4df 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -45,6 +45,10 @@ def fake_catalog_config(): @pytest.fixture def fake_catalog_with_overlapping_factories(): config = { + "an_example_dataset": { + "type": "pandas.CSVDataSet", + "filepath": "dummy_filepath", + }, "an_example_{placeholder}": { "type": "dummy_type", "filepath": "dummy_filepath", From e11638c96b819c6f8c7a9b34d38b021aa4a752ed Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Wed, 19 Jul 2023 10:20:52 +0100 Subject: [PATCH 11/17] Update command name in RELEASE.md Signed-off-by: Ahdra Merali --- RELEASE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index 0dfa1da9fd..7653b29fd4 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -13,7 +13,7 @@ ## Major features and improvements * Added dataset factories feature which uses pattern matching to reduce the number of catalog entries. * Activated all built-in resolvers by default for `OmegaConfigLoader` except for `oc.env`. -* Added `kedro catalog factories` CLI command. +* Added `kedro catalog factory list` CLI command. ## Bug fixes and other changes * Updated `kedro catalog list` to work with dataset factories. From fd0c51ff9c3dc66e5fd4eaa54e06d73360f88cfb Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 20 Jul 2023 10:49:49 +0100 Subject: [PATCH 12/17] Fix cli command definition Signed-off-by: Ahdra Merali --- kedro/framework/cli/catalog.py | 6 +++++- tests/framework/cli/test_catalog.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/kedro/framework/cli/catalog.py b/kedro/framework/cli/catalog.py index c0e5d584fa..fea920ea89 100644 --- a/kedro/framework/cli/catalog.py +++ b/kedro/framework/cli/catalog.py @@ -179,7 +179,11 @@ def create_catalog(metadata: ProjectMetadata, pipeline_name, env): click.echo("All datasets are already configured.") -@catalog.command("factory list") +@catalog.group() +def factory(): + """Command for working with catalog factories""" + +@factory.command("list") @env_option @click.pass_obj def list_patterns(metadata: ProjectMetadata, env): diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index 880828e4df..2ab4b36939 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -406,7 +406,7 @@ def test_list_catalog_factories( ) result = CliRunner().invoke( - fake_project_cli, ["catalog", "factory list"], obj=fake_metadata + fake_project_cli, ["catalog", "factory", "list"], obj=fake_metadata ) assert not result.exit_code From d59cee1018e0636f7462c023accbe82827a04b18 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 20 Jul 2023 13:03:08 +0100 Subject: [PATCH 13/17] Align terminology Signed-off-by: Ahdra Merali --- kedro/framework/cli/catalog.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kedro/framework/cli/catalog.py b/kedro/framework/cli/catalog.py index fea920ea89..d8901cd936 100644 --- a/kedro/framework/cli/catalog.py +++ b/kedro/framework/cli/catalog.py @@ -181,13 +181,14 @@ def create_catalog(metadata: ProjectMetadata, pipeline_name, env): @catalog.group() def factory(): - """Command for working with catalog factories""" + """Commands for working with catalog dataset factories""" + @factory.command("list") @env_option @click.pass_obj -def list_patterns(metadata: ProjectMetadata, env): - "Show all factory patterns in the catalog, ranked by priority by which they are matched." +def list_factories(metadata: ProjectMetadata, env): + """Show all dataset factories in the catalog, ranked by priority by which they are matched.""" session = _create_session(metadata.package_name, env=env) context = session.load_context() From a8657db7e146de1e7b0a0667d13ba642d0ef30d8 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 20 Jul 2023 13:57:02 +0100 Subject: [PATCH 14/17] Add message for no dataset factories Signed-off-by: Ahdra Merali --- kedro/framework/cli/catalog.py | 5 ++++- tests/framework/cli/test_catalog.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/kedro/framework/cli/catalog.py b/kedro/framework/cli/catalog.py index d8901cd936..2cc4769775 100644 --- a/kedro/framework/cli/catalog.py +++ b/kedro/framework/cli/catalog.py @@ -193,7 +193,10 @@ def list_factories(metadata: ProjectMetadata, env): context = session.load_context() catalog_factories = context.catalog._dataset_patterns - click.echo(yaml.dump(list(catalog_factories.keys()))) + if catalog_factories: + click.echo(yaml.dump(list(catalog_factories.keys()))) + else: + click.echo("There are no dataset factories in the catalog.") def _add_missing_datasets_to_catalog(missing_ds, catalog_path): diff --git a/tests/framework/cli/test_catalog.py b/tests/framework/cli/test_catalog.py index 2ab4b36939..5ed8c3d370 100644 --- a/tests/framework/cli/test_catalog.py +++ b/tests/framework/cli/test_catalog.py @@ -419,3 +419,28 @@ def test_list_catalog_factories( assert yaml_dump_mock.call_count == 1 assert yaml_dump_mock.call_args[0][0] == expected_patterns_sorted + + +@pytest.mark.usefixtures( + "chdir_to_dummy_project", + "fake_load_context", +) +def test_list_factories_with_no_factories( + fake_project_cli, fake_metadata, fake_load_context +): + mocked_context = fake_load_context.return_value + + catalog_data_sets = { + "iris_data": CSVDataSet("test.csv"), + "intermediate": MemoryDataset(), + "not_used": CSVDataSet("test2.csv"), + } + mocked_context.catalog = DataCatalog(data_sets=catalog_data_sets) + + result = CliRunner().invoke( + fake_project_cli, ["catalog", "factory", "list"], obj=fake_metadata + ) + + assert not result.exit_code + expected_output = "There are no dataset factories in the catalog." + assert expected_output in result.output From 49bf326645b90b5668fa233f200fe580581d941c Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 20 Jul 2023 18:08:14 +0100 Subject: [PATCH 15/17] Refactor test with iterative approach Signed-off-by: Ahdra Merali --- tests/tools/test_cli.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/tools/test_cli.py b/tests/tools/test_cli.py index 1b80ad8064..e65b4c6f9b 100644 --- a/tests/tools/test_cli.py +++ b/tests/tools/test_cli.py @@ -139,14 +139,14 @@ def test_get_cli_structure_help(self, mocker, fake_metadata): assert isinstance(help_cli_structure, dict) assert isinstance(help_cli_structure["kedro"], dict) - for k, v in help_cli_structure["kedro"].items(): + cli_commands = list(help_cli_structure["kedro"].items()) + + while cli_commands: + k, v = cli_commands[0] + cli_commands.pop(0) assert isinstance(k, str) if isinstance(v, dict): - for sub_key in v: - assert isinstance(help_cli_structure["kedro"][k][sub_key], str) - assert help_cli_structure["kedro"][k][sub_key].startswith( - "Usage: [OPTIONS]" - ) + cli_commands = cli_commands + list(v.items()) elif isinstance(v, str): assert v.startswith("Usage: [OPTIONS]") From e7723e912ea2e190d6c41372806ff542fe5a86a5 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Thu, 20 Jul 2023 18:09:36 +0100 Subject: [PATCH 16/17] Refactor with recursive approach Signed-off-by: Ahdra Merali --- tests/tools/test_cli.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/tools/test_cli.py b/tests/tools/test_cli.py index e65b4c6f9b..323d310e88 100644 --- a/tests/tools/test_cli.py +++ b/tests/tools/test_cli.py @@ -139,17 +139,18 @@ def test_get_cli_structure_help(self, mocker, fake_metadata): assert isinstance(help_cli_structure, dict) assert isinstance(help_cli_structure["kedro"], dict) - cli_commands = list(help_cli_structure["kedro"].items()) - - while cli_commands: - k, v = cli_commands[0] - cli_commands.pop(0) - assert isinstance(k, str) - if isinstance(v, dict): - cli_commands = cli_commands + list(v.items()) - elif isinstance(v, str): - assert v.startswith("Usage: [OPTIONS]") + self.recursive_cli_structure_test(help_cli_structure["kedro"]) assert sorted(list(help_cli_structure["kedro"])) == sorted( DEFAULT_KEDRO_COMMANDS ) + + def recursive_cli_structure_test(self, structure): + for k, v in structure.items(): + assert isinstance(k, str) + if isinstance(v, str): + assert v.startswith("Usage: [OPTIONS]") + elif isinstance(v, dict): + self.recursive_cli_structure_test(v) + else: # Should never be reached + pytest.fail() From 0b04fa477da7f6d62662c7b243a1bf61bbb26943 Mon Sep 17 00:00:00 2001 From: Ahdra Merali Date: Fri, 21 Jul 2023 14:44:10 +0100 Subject: [PATCH 17/17] Apply suggestions from review Signed-off-by: Ahdra Merali --- tests/tools/test_cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/tools/test_cli.py b/tests/tools/test_cli.py index 323d310e88..bc21a313f9 100644 --- a/tests/tools/test_cli.py +++ b/tests/tools/test_cli.py @@ -139,18 +139,18 @@ def test_get_cli_structure_help(self, mocker, fake_metadata): assert isinstance(help_cli_structure, dict) assert isinstance(help_cli_structure["kedro"], dict) - self.recursive_cli_structure_test(help_cli_structure["kedro"]) + self.recursively_check_cli_structure(help_cli_structure["kedro"]) assert sorted(list(help_cli_structure["kedro"])) == sorted( DEFAULT_KEDRO_COMMANDS ) - def recursive_cli_structure_test(self, structure): + def recursively_check_cli_structure(self, structure): for k, v in structure.items(): assert isinstance(k, str) if isinstance(v, str): assert v.startswith("Usage: [OPTIONS]") elif isinstance(v, dict): - self.recursive_cli_structure_test(v) + self.recursively_check_cli_structure(v) else: # Should never be reached pytest.fail()