From 0cec8c42c0a3c994285b93db5ee2881042586672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Gon=C3=A7alves?= Date: Thu, 6 Oct 2022 22:33:48 +0200 Subject: wip: decorator + arguments tests --- pydanclick/core.py | 17 ++++++++++------- tests/__init__.py | 0 tests/conftest.py | 28 ++++++++++++++++++++++++++-- tests/test_core.py | 38 ++++++++++++++++++++++++++++++++++---- 4 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 tests/__init__.py diff --git a/pydanclick/core.py b/pydanclick/core.py index 38285cc..a513852 100644 --- a/pydanclick/core.py +++ b/pydanclick/core.py @@ -3,7 +3,7 @@ from __future__ import annotations import click import inspect -from typing import Any, Union +from typing import Any from pydantic import BaseModel from typing import Callable, Type @@ -117,12 +117,6 @@ def get_option_arguments( case "boolean": arguments.type = bool arguments.is_flag = True - case None: - if parameter.ref: - definition = schema.get_definition_from_ref(parameter.ref) - arguments = get_option_arguments( - schema, definition, key, *args, **kwargs - ) return arguments @@ -154,6 +148,15 @@ def generate_cli_option( """ option_title = key.lower().replace("_", "-") + arguments = get_option_arguments(schema, parameter, key) + + # None arguments are usually Enum or nested pydantic structure. + # Putting that block in "get_option_arguments" pattern matching can make + # the completion crazy (infinite recursivity). + if arguments.type is None and parameter.ref: + definition = schema.get_definition_from_ref(parameter.ref) + arguments = get_option_arguments(schema, definition, key) + return click.option( f"--{key_prefix}{option_title}", **dict(get_option_arguments(schema, parameter, key)) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py index e598a79..7d5e2c7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,10 @@ +import click +import pytest + from enum import Enum from pydantic import BaseModel, Field - -import pytest +from pydanclick import core +from typing import Generator class GenericArguments(BaseModel): @@ -15,3 +18,24 @@ class GenericArguments(BaseModel): version: int = Field(gt=0) force: bool = Field(default=False, description="Force ABC.") fruit: FruitEnum + + +@pytest.fixture +def valid_arguments() -> Generator[GenericArguments, None, None]: + yield GenericArguments( + name="fruit_manager", + version=12, + force=True, + fruit="pineapple", + ) + + +@pytest.fixture +def valid_command_entrypoint() -> Generator[click.Command, None, None]: + + @click.command() + @core.generate_cli_options() + def entrypoint(parameters: GenericArguments): + pass + + yield entrypoint diff --git a/tests/test_core.py b/tests/test_core.py index 5993abc..cc4755f 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1,8 +1,38 @@ +import click +import pickle import pytest -from pydanclick import core, schemas -from tests.conftest import GenericArguments +def test_get_option_arguments_ok(valid_arguments): + # core.get_option_arguments(schema, parameter, "mega-option") + pass -def test_get_option_arguments_ok(): - core.get_option_arguments() + +def test_generate_cli_options_start(valid_command_entrypoint): + + with pytest.raises(SystemExit): + valid_command_entrypoint() + + +@pytest.mark.parametrize( + "argument_info", + [ + ["name", ["--name"], click.STRING], + ["version", ["--version"], click.IntRange(min=0)], + ["force", ["--force"], click.BOOL], + ["fruit", ["--fruit"], click.STRING], + ] +) +def test_generate_cli_options_arguments( + valid_command_entrypoint, + argument_info, +): + option = next( + filter( + lambda el: el.name == argument_info[0], + valid_command_entrypoint.params + ) + ) + + assert option.opts == argument_info[1] + assert pickle.dumps(option.type) == pickle.dumps(argument_info[2]) -- cgit v1.2.3