Open anentropic opened 1 year ago
I can annotate them like
first_name: factory.Faker[Any, str] = factory.Faker("first_name")
I think that's right? not sure what the first type param represents
I have the same issue with SubFactory
user = factory.SubFactory(UserFactory)
blog/factories.py:38: error: Need type annotation for "user" [var-annotated]
The thing is that Factory classes can't really be instantiated, so whatever we decide here doesn't really matter in this sense. That being said, it's indeed annoying that we have to type every single line.
Maybe these factory fields should be annotated with the same type as the model? If so, it's doable to write a mypy plugin that fills them in for you.
But I would need to see some use cases of how these fields annotation can actually be used for something.
For example, maybe we can tell the type checker that the argument of LazyAttribute is an instance of the factory class (although it isn't), and then we could access this class with correct types.
I'm not sure if I was clear, I'm not 100% sure either of how things should work in these cases.
my main motivation is just to make the errors go away...
for now I have just excluded my factories.py
from mypy 😀
Hitting this today.
Maybe these factory fields should be annotated with the same type as the model?
When I do something like user: User = factory.SubFactory(UserFactory)
, I get:
file.py: error: Incompatible types in assignment
(expression has type "SubFactory[<nothing>, Any]", variable has type "User")
[assignment]
user: User = factory.SubFactory(UserFactory)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So that's not working out for me, mypy
is throwing an assignment
error. Anything I can do from there?
I'm not sure tbh
Not really a solution to the actual problem, but as a workaround you could use LazyFunction
with faker directly, for example:
import factory
import faker
fake = faker.Faker()
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
username = factory.Sequence(lambda n: f"{_faker.user_name()}_{n:08}")
first_name = factory.LazyFunction(fake.first_name)
last_name = factory.LazyFunction(fake.last_name)
email = factory.LazyFunction(fake.ascii_safe_email)
That at least seems to keep mypy quiet for now :laughing: Faker itself is a typed package, so maybe that's why.
I have factories like:
with mypy 0.982 I get:
so all the
factory.Faker
fields have a problemI can guess this is probably due to the way
factory.Faker
itself is implemented - the type of the faker depends on the value of the string arg and there's no way for type info fromfaker
itself to flow through that interface.I guess the only way for that to work would be to tediously define an
@overload
withLiteral[<method name>]
for each faker method? Maybe that's not even possible either.