From a8613cc8fc5d263e8d2d9ee92006e747f60d274b Mon Sep 17 00:00:00 2001 From: Dave Date: Fri, 20 Dec 2024 11:05:41 +0100 Subject: [PATCH 1/3] extending features example --- dlt/feature/__init__.py | 10 +++++++++ dlt/feature/impl.py | 6 ++++++ dlt/feature/reference.py | 5 +++++ .../dlt_example_plugin/feature/__init__.py | 21 +++++++++++++++++++ tests/plugins/test_plugin_discovery.py | 13 +++++++++++- tests/plugins/test_simple_feature.py | 5 +++++ 6 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 dlt/feature/__init__.py create mode 100644 dlt/feature/impl.py create mode 100644 dlt/feature/reference.py create mode 100644 tests/plugins/dlt_example_plugin/dlt_example_plugin/feature/__init__.py create mode 100644 tests/plugins/test_simple_feature.py diff --git a/dlt/feature/__init__.py b/dlt/feature/__init__.py new file mode 100644 index 0000000000..e3eff5b72b --- /dev/null +++ b/dlt/feature/__init__.py @@ -0,0 +1,10 @@ +try: + from dlt_example_plugin.feature import ExtendedFeature as SupportsFeature + from dlt_example_plugin.feature import ExtendedFeature as Feature +except ImportError: + from dlt.feature.reference import SupportsSimpleFeature as SupportsFeature + from dlt.feature.impl import SimpleFeature as Feature + + +def get_feature() -> SupportsFeature: + return Feature() diff --git a/dlt/feature/impl.py b/dlt/feature/impl.py new file mode 100644 index 0000000000..51b8ad74e1 --- /dev/null +++ b/dlt/feature/impl.py @@ -0,0 +1,6 @@ +from dlt.feature.reference import SupportsSimpleFeature + + +class SimpleFeature(SupportsSimpleFeature): + def calculate(self, a: int, b: int) -> int: + return a + b diff --git a/dlt/feature/reference.py b/dlt/feature/reference.py new file mode 100644 index 0000000000..281e480dce --- /dev/null +++ b/dlt/feature/reference.py @@ -0,0 +1,5 @@ +from typing import Protocol + + +class SupportsSimpleFeature(Protocol): + def calculate(self, a: int, b: int) -> int: ... diff --git a/tests/plugins/dlt_example_plugin/dlt_example_plugin/feature/__init__.py b/tests/plugins/dlt_example_plugin/dlt_example_plugin/feature/__init__.py new file mode 100644 index 0000000000..c45516e8e2 --- /dev/null +++ b/tests/plugins/dlt_example_plugin/dlt_example_plugin/feature/__init__.py @@ -0,0 +1,21 @@ +from typing import TYPE_CHECKING + +from dlt.feature.impl import SimpleFeature +from dlt.feature.reference import SupportsSimpleFeature + + +# extend interface +class SupportsExtendedFeature(SupportsSimpleFeature): + # add new method + def more_calculation(self, a: int, b: int) -> int: ... + + +# extend implementation +class ExtendedFeature(SupportsExtendedFeature, SimpleFeature): + # override a method + def calculate(self, a: int, b: int) -> int: + return a * b + + # add a new method + def more_calculation(self, a: int, b: int) -> int: + return a**b diff --git a/tests/plugins/test_plugin_discovery.py b/tests/plugins/test_plugin_discovery.py index 6962e89bf7..c6ffbe9735 100644 --- a/tests/plugins/test_plugin_discovery.py +++ b/tests/plugins/test_plugin_discovery.py @@ -45,15 +45,18 @@ def plugin_install(): sys.path.remove(temp_dir) shutil.rmtree(temp_dir) importlib.reload(importlib.metadata) - del container[plugins.PluginContext] + if plugins.PluginContext in container: + del container[plugins.PluginContext] +@pytest.mark.skip def test_example_plugin() -> None: context = run_context.current() assert context.name == "dlt-test" assert context.data_dir == os.path.abspath(TEST_STORAGE_ROOT) +@pytest.mark.skip def test_cli_hook(script_runner: ScriptRunner) -> None: # new command result = script_runner.run(["dlt", "example", "--name", "John"]) @@ -83,3 +86,11 @@ def test_cli_hook(script_runner: ScriptRunner) -> None: assert result.returncode == -55 assert "Plugin overwrote init command" in result.stdout assert "INIT_DOCS_URL" in result.stdout + + +def test_extended_feature(): + from dlt.feature import get_feature + + feature = get_feature() + assert feature.calculate(3, 3) == 9 + assert feature.more_calculation(3, 3) == 27 diff --git a/tests/plugins/test_simple_feature.py b/tests/plugins/test_simple_feature.py new file mode 100644 index 0000000000..2fb4041d1c --- /dev/null +++ b/tests/plugins/test_simple_feature.py @@ -0,0 +1,5 @@ +def test_simple_feature(): + from dlt.feature import get_feature + + feature = get_feature() + assert feature.calculate(3, 3) == 6 From eb51f2ec35acbb873fe17f9508897f7146e07694 Mon Sep 17 00:00:00 2001 From: Dave Date: Fri, 20 Dec 2024 11:10:47 +0100 Subject: [PATCH 2/3] remove skipping --- tests/plugins/test_plugin_discovery.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plugins/test_plugin_discovery.py b/tests/plugins/test_plugin_discovery.py index c6ffbe9735..a47bc8db82 100644 --- a/tests/plugins/test_plugin_discovery.py +++ b/tests/plugins/test_plugin_discovery.py @@ -49,14 +49,14 @@ def plugin_install(): del container[plugins.PluginContext] -@pytest.mark.skip + + def test_example_plugin() -> None: context = run_context.current() assert context.name == "dlt-test" assert context.data_dir == os.path.abspath(TEST_STORAGE_ROOT) -@pytest.mark.skip def test_cli_hook(script_runner: ScriptRunner) -> None: # new command result = script_runner.run(["dlt", "example", "--name", "John"]) From 741ef50e6fe9695f598466ee81f3ae31ec6a277b Mon Sep 17 00:00:00 2001 From: Dave Date: Fri, 20 Dec 2024 11:14:20 +0100 Subject: [PATCH 3/3] fix extended protocol import in decorator --- dlt/feature/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlt/feature/__init__.py b/dlt/feature/__init__.py index e3eff5b72b..c36f28de0f 100644 --- a/dlt/feature/__init__.py +++ b/dlt/feature/__init__.py @@ -1,5 +1,5 @@ try: - from dlt_example_plugin.feature import ExtendedFeature as SupportsFeature + from dlt_example_plugin.feature import SupportsExtendedFeature as SupportsFeature from dlt_example_plugin.feature import ExtendedFeature as Feature except ImportError: from dlt.feature.reference import SupportsSimpleFeature as SupportsFeature