diff --git a/pyproject.toml b/pyproject.toml index d5a932a1..568a3a93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ test = [ "build>=1.2.0,<1.3", "deepdiff>=8.0,<9.0", "hypothesis>=6.0.0,<7", + "inline-snapshot>=0.29.4,<1", "parameterized>=0.9.0,<0.10", "pip>=24.0", "pytest>=8.0.0,<9.0.0", diff --git a/tests/commands/test_plugins.py b/tests/commands/test_plugins.py index ae8a0e46..133948c1 100644 --- a/tests/commands/test_plugins.py +++ b/tests/commands/test_plugins.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING +from inline_snapshot import snapshot from variantlib.commands.main import main if TYPE_CHECKING: @@ -28,25 +29,46 @@ def test_plugins_get_all_configs( mocked_entry_points: None, ) -> None: main(["plugins", "get-configs", "--all"]) - assert ( - capsys.readouterr().out - == """\ -test_namespace :: name1 :: val1a -test_namespace :: name1 :: val1b -test_namespace :: name1 :: val1c -test_namespace :: name1 :: val1d -test_namespace :: name2 :: val2a -test_namespace :: name2 :: val2b -test_namespace :: name2 :: val2c -second_namespace :: name3 :: val3a -second_namespace :: name3 :: val3b -second_namespace :: name3 :: val3c -incompatible_namespace :: flag1 :: on -incompatible_namespace :: flag2 :: on -incompatible_namespace :: flag3 :: on -incompatible_namespace :: flag4 :: on -""" - ) + assert capsys.readouterr().out == snapshot("""\ +test_namespace: + - name: name1 + multi_value: false + values: + - val1a + - val1b + - val1c + - val1d + - name: name2 + multi_value: true + values: + - val2a + - val2b + - val2c +second_namespace: + - name: name3 + multi_value: false + values: + - val3a + - val3b + - val3c +incompatible_namespace: + - name: flag1 + multi_value: false + values: + - on + - name: flag2 + multi_value: false + values: + - on + - name: flag3 + multi_value: false + values: + - on + - name: flag4 + multi_value: false + values: + - on +""") def test_plugins_get_all_configs_filter_namespace( @@ -54,14 +76,15 @@ def test_plugins_get_all_configs_filter_namespace( mocked_entry_points: None, ) -> None: main(["plugins", "get-configs", "--all", "-n", "second_namespace"]) - assert ( - capsys.readouterr().out - == """\ -second_namespace :: name3 :: val3a -second_namespace :: name3 :: val3b -second_namespace :: name3 :: val3c -""" - ) + assert capsys.readouterr().out == snapshot("""\ +second_namespace: + - name: name3 + multi_value: false + values: + - val3a + - val3b + - val3c +""") def test_plugins_get_all_configs_filter_feature( @@ -69,15 +92,18 @@ def test_plugins_get_all_configs_filter_feature( mocked_entry_points: None, ) -> None: main(["plugins", "get-configs", "--all", "-f", "name1"]) - assert ( - capsys.readouterr().out - == """\ -test_namespace :: name1 :: val1a -test_namespace :: name1 :: val1b -test_namespace :: name1 :: val1c -test_namespace :: name1 :: val1d -""" - ) + assert capsys.readouterr().out == snapshot("""\ +test_namespace: + - name: name1 + multi_value: false + values: + - val1a + - val1b + - val1c + - val1d +second_namespace: [] +incompatible_namespace: [] +""") def test_plugins_get_supported_configs( @@ -85,17 +111,25 @@ def test_plugins_get_supported_configs( mocked_entry_points: None, ) -> None: main(["plugins", "get-configs", "--supported"]) - assert ( - capsys.readouterr().out - == """\ -test_namespace :: name1 :: val1a -test_namespace :: name1 :: val1b -test_namespace :: name2 :: val2a -test_namespace :: name2 :: val2b -test_namespace :: name2 :: val2c -second_namespace :: name3 :: val3a -""" - ) + assert capsys.readouterr().out == snapshot("""\ +test_namespace: + - name: name1 + multi_value: false + values: + - val1a + - val1b + - name: name2 + multi_value: true + values: + - val2a + - val2b + - val2c +second_namespace: + - name: name3 + multi_value: false + values: + - val3a +""") def test_plugins_get_supported_configs_filter_namespace( @@ -103,12 +137,13 @@ def test_plugins_get_supported_configs_filter_namespace( mocked_entry_points: None, ) -> None: main(["plugins", "get-configs", "--supported", "-n", "second_namespace"]) - assert ( - capsys.readouterr().out - == """\ -second_namespace :: name3 :: val3a -""" - ) + assert capsys.readouterr().out == snapshot("""\ +second_namespace: + - name: name3 + multi_value: false + values: + - val3a +""") def test_plugins_get_supported_configs_filter_feature( @@ -116,10 +151,12 @@ def test_plugins_get_supported_configs_filter_feature( mocked_entry_points: None, ) -> None: main(["plugins", "get-configs", "--supported", "-f", "name1"]) - assert ( - capsys.readouterr().out - == """\ -test_namespace :: name1 :: val1a -test_namespace :: name1 :: val1b -""" - ) + assert capsys.readouterr().out == snapshot("""\ +test_namespace: + - name: name1 + multi_value: false + values: + - val1a + - val1b +second_namespace: [] +""") diff --git a/uv.lock b/uv.lock index 53f07824..3296569c 100644 --- a/uv.lock +++ b/uv.lock @@ -2,6 +2,15 @@ version = 1 revision = 3 requires-python = ">=3.10" +[[package]] +name = "asttokens" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978, upload-time = "2024-11-30T04:30:14.439Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918, upload-time = "2024-11-30T04:30:10.946Z" }, +] + [[package]] name = "attrs" version = "25.3.0" @@ -191,6 +200,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612, upload-time = "2024-04-08T09:04:17.414Z" }, ] +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + [[package]] name = "filelock" version = "3.19.1" @@ -244,6 +262,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] +[[package]] +name = "inline-snapshot" +version = "0.29.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pytest" }, + { name = "rich" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/20/72be6fa80b3228693e70f058736bf8ea0ea812b555b90def3e5400d408a3/inline_snapshot-0.29.4.tar.gz", hash = "sha256:b76d08ddd794a0286e7c0d5124cba64dd75d94c0a1b9a50ad13e96e0953597d1", size = 2598478, upload-time = "2025-10-13T07:40:50.055Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ac/9f/12c9ba11496fc3111d159d3cf2902bf21fc42c6b71380e06bcbc12edf9ff/inline_snapshot-0.29.4-py3-none-any.whl", hash = "sha256:310bc09d0ec226c00e003ec3a91592e44aa12d3c187af1a29e5a76843c59191e", size = 71096, upload-time = "2025-10-13T07:40:48.659Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + [[package]] name = "mypy" version = "1.15.0" @@ -488,6 +543,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, ] +[[package]] +name = "rich" +version = "14.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, +] + [[package]] name = "ruff" version = "0.13.1" @@ -645,6 +713,7 @@ test = [ { name = "build" }, { name = "deepdiff" }, { name = "hypothesis" }, + { name = "inline-snapshot" }, { name = "parameterized" }, { name = "pip" }, { name = "pytest" }, @@ -663,6 +732,7 @@ requires-dist = [ { name = "deepdiff", marker = "extra == 'test'", specifier = ">=8.0,<9.0" }, { name = "hypothesis", marker = "extra == 'test'", specifier = ">=6.0.0,<7" }, { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, + { name = "inline-snapshot", marker = "extra == 'test'", specifier = ">=0.29.4,<1" }, { name = "mypy", marker = "extra == 'dev'", specifier = "==1.15.0" }, { name = "packaging", specifier = ">=25.0,<26.0" }, { name = "parameterized", marker = "extra == 'test'", specifier = ">=0.9.0,<0.10" }, diff --git a/variantlib/commands/plugins/get_configs.py b/variantlib/commands/plugins/get_configs.py index 1f7b1d2d..99c85452 100644 --- a/variantlib/commands/plugins/get_configs.py +++ b/variantlib/commands/plugins/get_configs.py @@ -6,7 +6,6 @@ from typing import TYPE_CHECKING from variantlib import __package_name__ -from variantlib.models.variant import VariantProperty if TYPE_CHECKING: from variantlib.plugins.loader import BasePluginLoader @@ -46,10 +45,24 @@ def get_configs(args: list[str], plugin_loader: BasePluginLoader) -> None: if parsed_args.namespace not in (provider_cfg.namespace, None): continue - for feature in provider_cfg.configs: - if parsed_args.feature not in (feature.name, None): - continue + matched_features = [ + feature + for feature in provider_cfg.configs + if parsed_args.feature in (feature.name, None) + ] - for value in feature.values: - vprop = VariantProperty(provider_cfg.namespace, feature.name, value) - sys.stdout.write(f"{vprop.to_str()}\n") + if matched_features: + sys.stdout.write(f"{provider_cfg.namespace}:\n") + for feature in provider_cfg.configs: + if parsed_args.feature not in (feature.name, None): + continue + + sys.stdout.write(f" - name: {feature.name}\n") + sys.stdout.write( + f" multi_value: {str(feature.multi_value).lower()}\n" + ) + sys.stdout.write(" values:\n") + for value in feature.values: + sys.stdout.write(f" - {value}\n") + else: + sys.stdout.write(f"{provider_cfg.namespace}: []\n")