Open raminqaf opened 7 months ago
Yes, this is definitely something that you can do. The problem with the code you have is that pff.cast(person=Person)
ends up calling Person({'first_name': 'John', 'last_name': 'Doe'})
(i.e. it passes the parameter read from the YAML file directly to the given callable), but pydantic constructors instead expect keyword arguments in the form of Person(first_name='John', last_name='Doe')
.
One easy way to solve this problem is to use Person.model_validate
instead of Person
. This factory function expects a single dictionary in the form that pff.cast()
provides, so everything just works:
import parametrize_from_file as pff
from pydantic import BaseModel
import builtins
class Person(BaseModel):
first_name: str
last_name: str
@pff.parametrize(schema=[pff.cast(person=Person.model_validate)])
def test_object(person: Person, len: int):
assert person.first_name == "John"
assert builtins.len(person.first_name) == len
Another possible way to solve this problem is to use a lambda function to expand out the keyword arguments yourself. In this specific case, I think the Person.model_validate
approach is better, but in other cases a lambda might make more sense:
@pff.parametrize(schema=[pff.cast(person=lambda x: Person(**x))])
def test_object(person: Person, len: int):
...
Let me know if you have any other questions, I'd be happy to help!
Nice! I used the first approach and it works! I am getting a warning from PyCharm on this part of the decorator: person=Person.model_validate
Expected type 'dict', got '(obj: Any, Any, strict: bool | None, from_attributes: bool | None, context: dict[str, Any] | None) -> Model' instead
Unfortunately, I have no idea what's going on with that warning. This reminds me a bit of #20, which also involves PyCharm generating warnings where it shouldn't. pff.cast()
doesn't have type-hints—maybe it would help if it did—but regardless it seems like PyCharm shouldn't be complaining about the type of an argument being passed to an untyped function...
Unfortunately, I have no idea what's going on with that warning. This reminds me a bit of #20, which also involves PyCharm generating warnings where it shouldn't.
pff.cast()
doesn't have type-hints—maybe it would help if it did—but regardless it seems like PyCharm shouldn't be complaining about the type of an argument being passed to an untyped function...
Maybe typing the function's input parameters and defining return types helps. For the warnings mentioned in #20 I changed this part of the code and managed to get rid of the parameter kwargs undefined
warning
@_decorator_factory
-def parametrize(param_names, param_values, kwargs):
@_decorator_factory
+def parametrize(param_names, param_values, **kwargs):
The other warning, parameter param_values undefined
, was still visible.
If adding **
in front of kwargs
has any effect on the warning, that's definitely a sign that there's a bug in PyCharm. Adding type hints wouldn't help. The signature of the pff.parametize()
as seen by end-users is determined by _decorator_factory()
and has no relation to the signature of the parametrize()
function itself. But PyCharm (or whatever linter it's using behind the scenes) doesn't seem smart enough to realize this.
Also, you should undo **kwargs
change you made, because it 100% breaks the code. Specifically, it will prevent you from passing any arguments through to pytest.mark.parametrize
.
Hello! I am using your library to parametrize my tests! I am using Pydantic in my project and would like to use it to (de)serialize the input objects with it. My test case looks as follows:
I don't know if I am using the
schema
and thecast
correctly in this context, but I would like to convert the complex object into a base model. Alternatively, I can do this:which works, but it would be nice if the library could do the conversion on its own! Is there a way of doing this?