mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 03:24:20 +00:00
✏️ Make commands coroutines
This commit is contained in:
parent
b8607edb56
commit
eb90daa241
3 changed files with 24 additions and 12 deletions
|
@ -40,11 +40,11 @@ def parameter_to_field(param: inspect.Parameter, **kwargs) -> Tuple[type, pydant
|
||||||
|
|
||||||
def signature_to_model(f: Callable, __config__: pydantic.BaseConfig = ModelConfig, **extra_params):
|
def signature_to_model(f: Callable, __config__: pydantic.BaseConfig = ModelConfig, **extra_params):
|
||||||
"""
|
"""
|
||||||
Convert the signature of a function to a pydantic model.
|
Convert the signature of a async function to a pydantic model.
|
||||||
|
|
||||||
Arguments starting with ``_`` are ignored.
|
Arguments starting with ``_`` are ignored.
|
||||||
|
|
||||||
:param f: The function to use the signature of.
|
:param f: The async function to use the signature of.
|
||||||
:param __config__: The config the pydantic model should use.
|
:param __config__: The config the pydantic model should use.
|
||||||
:param extra_params: Extra parameters to be added to the model.
|
:param extra_params: Extra parameters to be added to the model.
|
||||||
:return: The created pydantic model.
|
:return: The created pydantic model.
|
||||||
|
|
|
@ -18,7 +18,8 @@ class EngineerRouter:
|
||||||
|
|
||||||
:param name: The name of the command (``start``, ``settings``, etc). If not specified, it will use the name
|
:param name: The name of the command (``start``, ``settings``, etc). If not specified, it will use the name
|
||||||
of the wrapped function.
|
of the wrapped function.
|
||||||
:param f: The function that should be executed when the command is called. It must have a ``.model`` property.
|
:param f: The async function that should be executed when the command is called.
|
||||||
|
It must have a ``.model`` property.
|
||||||
|
|
||||||
.. seealso:: :meth:`.command`, :func:`.params.function_with_model`
|
.. seealso:: :meth:`.command`, :func:`.params.function_with_model`
|
||||||
"""
|
"""
|
||||||
|
@ -33,13 +34,13 @@ class EngineerRouter:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@command()
|
@command()
|
||||||
def ping():
|
async def ping():
|
||||||
print("Pong!")
|
print("Pong!")
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@command(name="ping")
|
@command(name="ping")
|
||||||
def xyzzy():
|
async def xyzzy():
|
||||||
print("Pong!")
|
print("Pong!")
|
||||||
|
|
||||||
:param name: The name of the command (``start``, ``settings``, etc). If not specified, it will use the name
|
:param name: The name of the command (``start``, ``settings``, etc). If not specified, it will use the name
|
||||||
|
@ -61,7 +62,18 @@ class EngineerRouter:
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
def call(self, __name: str, **kwargs):
|
async def call(self, __name: str, **kwargs) -> Any:
|
||||||
|
"""
|
||||||
|
Call the command with the specified name using the passed kwargs.
|
||||||
|
|
||||||
|
:param __name: The name of the function.
|
||||||
|
:param kwargs: Kwargs to pass to the desired function:
|
||||||
|
- Kwargs starting with ``__`` are never passed to the function.
|
||||||
|
- Kwargs starting with ``_`` are passed as they are.
|
||||||
|
- Other kwargs are validated by the function's :mod:`pydantic` model.
|
||||||
|
:return: The return value of the function.
|
||||||
|
:raises pydantic.ValidationError: If the kwargs do not pass the :mod:`pydantic` model validation.
|
||||||
|
"""
|
||||||
model_params = {}
|
model_params = {}
|
||||||
extra_params = {}
|
extra_params = {}
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
|
@ -74,7 +86,7 @@ class EngineerRouter:
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
Model: Type[pydantic.BaseModel] = f.model
|
Model: Type[pydantic.BaseModel] = f.model
|
||||||
model: pydantic.BaseModel = Model(**model_params)
|
model: pydantic.BaseModel = Model(**model_params)
|
||||||
return f(**model.dict(), **extra_params)
|
return await f(**model.dict(), **extra_params)
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
|
|
|
@ -6,14 +6,14 @@ import royalnet.engineer as re
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def a_random_function():
|
async def my_async_function():
|
||||||
def f(*, big_f: str, _hidden: int) -> str:
|
def f(*, big_f: str, _hidden: int) -> str:
|
||||||
return big_f
|
return big_f
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
def test_parameter_to_field(a_random_function):
|
def test_parameter_to_field(my_async_function):
|
||||||
signature = inspect.signature(a_random_function)
|
signature = inspect.signature(my_async_function)
|
||||||
parameter = signature.parameters["big_f"]
|
parameter = signature.parameters["big_f"]
|
||||||
t, fieldinfo = re.parameter_to_field(parameter)
|
t, fieldinfo = re.parameter_to_field(parameter)
|
||||||
assert isinstance(fieldinfo, pydantic.fields.FieldInfo)
|
assert isinstance(fieldinfo, pydantic.fields.FieldInfo)
|
||||||
|
@ -21,8 +21,8 @@ def test_parameter_to_field(a_random_function):
|
||||||
assert fieldinfo.title == parameter.name == "big_f"
|
assert fieldinfo.title == parameter.name == "big_f"
|
||||||
|
|
||||||
|
|
||||||
def test_signature_to_model(a_random_function):
|
def test_signature_to_model(my_async_function):
|
||||||
Model = re.signature_to_model(a_random_function)
|
Model = re.signature_to_model(my_async_function)
|
||||||
assert callable(Model)
|
assert callable(Model)
|
||||||
|
|
||||||
model = Model(big_f="banana")
|
model = Model(big_f="banana")
|
||||||
|
|
Loading…
Reference in a new issue