New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support type hinting? #468
Comments
Yep, that would be a great idea! But I'm not sure how this could be easily done. A simple workaround could be to use |
for me PyCharm can't even find the As for the |
I haven't tried this with Mypy, but this will get the case of
Currently I'm doing this for each factory as a quick and dirty fix. Hopefully it's possible to move this up to the parent Factory class, maybe using Generics? (https://mypy.readthedocs.io/en/stable/generics.html ) |
Has anyone tried type hinting with a E.g.
Now the problem that I face here is, in the So how should we handle this? |
Typing support would be really nice! |
my workaround for missing General protocol is as follow: T = TypeVar("T")
class BaseFactory(Generic[T], factory.Factory):
@classmethod
def create(cls, **kwargs) -> T:
return super().create(**kwargs)
class RoleFactory(BaseFactory[Role]):
class Meta:
model = Role
id = factory.Sequence(lambda n: n)
name = factory.Sequence(lambda n: f"Role {n}") one drawback of this solution is that you always need to use |
@kamilglod I think it's a great workaround! Thank you! |
Thanks @kamilglod for the excellent workaround. There's still the issue of the |
@Ragura good question. All ideas that comes to my mind are equally complicated as manually typing first argument each time new method is added. It might be possible on python 3.10 which comes with better params typing support (https://docs.python.org/3.10/library/typing.html#typing.ParamSpec) but I do not have enough spare time to dig into it. I was trying to override post_generation class like this: class post_generation(Generic[T]):
def __init__(self, func: Callable[[BaseFactory[T], Callable, bool], str]):
self.func = func
def __call__(self) -> Callable[[T, Callable, bool], str]:
return factory.post_generation(self.func) but mypy still does not see class RoleFactory(BaseFactory[Role]):
class Meta:
model = Role
id = factory.Sequence(lambda n: n)
name = factory.Sequence(lambda n: f"Role {n}")
@post_generation
def mbox(obj, create, extracted, **kwargs):
reveal_type(obj) # Type of "obj" is "RoleFactory"
return "foo" |
I'm using this trick currently which seems to play nice with the (Pylance) type checker in vscode.
|
As far as what changes could actually be implemented in this library - FactoryBoy just needs to aim for mypy compliance. This really wouldn't be terrible, adding type hints is always relatively quick. I'd assume the maintainers would be open to a related PR. The trickiest problem is what's discussed here, binding a "generic" type to the type of a meta class member. To my knowledge this unfortunately isn't directly possible. That means using the generics (per @kamilglod) is the most accurate way to accomplish this, to my knowledge. The downside is, of course, that the user must then specify the model in two places (in the base class generic binding, and in the metaclass) but at least having this option would be huge, and would mean that FactoryBoy could reach mypy compliance using generics until (if) a better binding method is discovered. I am currently on a hunt to figure out if there's a better way to bind typevars to class members or metaclass members (for something unrelated), currently with 0 luck. My stackoverflow question is as-of now unsuccessful, I'm still hoping for a response on the python discord as a fallback. |
@tgross35 My actual factory declarations are most usually defined with string values in their meta model, either future references or keys for a class registry to avoid import-time troubles while an application / DB connection are not ready. The
@yunuscanemre Just watch out for the tricky |
Maintainers are not interested in adding type hints or what? |
Hi 👋 I'm interested in helping here. I did this on Uvicorn: encode/uvicorn#998. Can I help here? |
I'm interested in this, but lacking time to work on the project at the moment — and an accumulated backlog of code to review before a next release :( Once I reduce said backlog and return to a smaller list of unreviewed changes, I would love to dig into this topic, along with others. (As a side note, passive-agressive comments are unlikely to entice unpaid maintainers motivated into spending time on said projects 😉) |
Some time ago I started experimenting with this https://github.com/n1ngu/factory_boy/tree/feature/typing The branch evolved chaotically so I got stuck and abandoned the idea. I am a bit clueless on how to address this incrementally so that it could be merged upstream with a sane review. But anyone feel free to pick any commit or idea from my experiment. Also, if someone starts working on this, don't hesitate to post you work in progress here so I could watch and maybe learn something. cc/ @Kludex |
I'll only help if a maintainer gives me a thumbs up to work on it, otherwise it will be a waste of time for the both of us. |
It is also possible to override metaclass, so you don't need to specify model in meta
|
@anton-fomin that's fantastic. thank you! |
@anton-fomin , is it possible to incorporate it into the main repo? Or do we see any possible issues? |
@sshishov , I don't know how it will affect other parts, but it definitely will involve updates to the documentation and tests. I am not sure I will find time to do that |
Sadly mypy does not supporte generic metaclass yet: python/mypy#11672 |
I think this could be closed as |
It's certainly the simplest workaround! 🙏🏻 Is there any disadvantage to using |
See FactoryBoy/factory_boy#468 PIDD: Pycharm inspection driven development 🤷
See FactoryBoy/factory_boy#468 PIDD: Pycharm inspection driven development 🤷
Not "disadvantage" per se but, in some cases like mine, it means updating 10k+ tests, which is not very enjoyable. |
thanks for sharing this :) so far i've just used a work around similar to @erdnaxeli 's suggestion, so it'd be great to use the newest |
Am I missing something or does this still need a PEP 561 |
I can't seem to have PyCharm play nice with the objects generated by Factory Boy; it would be nice to either automatically support type hinting somehow (ideally, it would simply be the model defined as a base for the factory) or at least add some documentation to explain how to have type checkers understand that,
after
p = PersonFactory()
, variuablep
is actually an instance ofPerson
rather than ofPersonFactory
.(Note: I'm not submitting a PR because I haven't figured out a solution)
The text was updated successfully, but these errors were encountered: