feat: Add basic typing support
This PR adds basic type hinting support
Refs #468
@rbarrois
hmm, i think, to properly test type annotations, we should add pyright and/or mypy to CI, run it over example file, and compare that to expected output.
But there is simpler option, we can do something like this:
def x() -> int:
...
assert x.__annotations__ == {"returns": int}
In theory, this should be enough to ensure we get expected annotations.
as for linking with Meta: model, yes, i don't see any way to do it.
Also, i see some failing CI checks, i'll try to fix it.
Oh, looks like all errors is from 3.6 version, lefetime of which is ended three weeks ago.
Maybe better solution in this case, is to remove old version from CI? But i'll try to find other solutions, maybe any ideas?
I haven't found easy workarounds for this, so i created PR for removing 3.6 from CI, and adding 3.10 and django-4.0.
Thanks, an other huge step would be to type the kwargs.
To be able to do UserFactory.create(xxx=yy) and have autocompletion on xxx.
I have no idea on how to do that, and even if it could be possible with python? 🤔
I think, it could be implemented. Python 3.10 added ParamSpec, and it could be used with older versions of python via typing-extensions, so i think it could be possible.
I found a way to properly type even calls to factory, turned out it was pretty simple.
Now types are correct with both possible ways to call a factory:
BookFactory() -> Book
BookFactory.create() -> Book
But, this all requires python 3.6 at least.
I think, it could be implemented. Python 3.10 added
ParamSpec, and it could be used with older versions of python via typing-extensions, so i think it could be possible.
I would love to see that!
I found a way to properly type even calls to factory, turned out it was pretty simple.
Turned out it doesn't work. Reverted changes back to only typing create, build, etc...
Now i'm trying to test it.
As for testing type annotations, i found one way to do it:
And it looks like this: https://github.com/smarie/python-decopatch/pull/27/files
- Install
pyright - Run it in json mode, compare results to snapshot
I could add similar tests for this package. (In this PR or next, preferrably next)
I fund myself today thinking it would be great to have types in my factories. Can we merge this, or we need to add tests first?
I started a project, types-factory-boy, to add type annotations to factory boy. It is in early stage, and it most probably needs a plugin to automatically discover and create type annotations automatically (otherwise you would have to type annotate basically every attribute), but I think it's a start.
When it comes to testing types and type annotations. I'd suggest: https://github.com/TypedDjango/pytest-mypy-plugins
Although it's a pytest plugin, so those tests needs to be run with pytest. Should be possible to add that as an individual job in CI etc.
Have a look at django-stubs https://github.com/typeddjango/django-stubs/tree/master/tests/typecheck for reference of how to use it and/or set it up.
@youtux great project, thank you.
After pyright fixed a bug with invalid init annotations and default values in 1.1.264, default factory_boy is throwing type errors sometimes (Maybe declaration for example).
Your project fixed it.
Is this ready for review again?
In basic form, yes.
But, we have https://github.com/youtux/types-factory-boy now, and i can try to merge it into this project with merge_pyi.
But, i think it's better to leave this PR in minimal form, maybe add tests for types in the next PR. And then - merge types-factory-boy for more complete type coverage.
~I think there was some misunderstanding here, as I don't understand @last-partizan message about merging types-factory-boy into this codebase.~
~types-factory-boy contains annotations for factory_boy lib (which I don't control), not for pytest_factoryboy (that I manage).~
EDIT: scrap that, I thought I was writing in the pytest_factoryboy project.
I made some progress in types-factory-boy. Now there is a mypy plugin that automatically adds the typevar information of the Factory[T] baseclass.
So, instead of writing this:
class AuthorFactory(Factory[Author]):
class Meta:
model = Author
reveal_type(AuthorFactory.create()) # foo.Author
we can write this:
class AuthorFactory(Factory): # No need to specify the typevar for Factory[...], it's inferred from Meta.model
class Meta:
model = Author
reveal_type(AuthorFactory.create()) # foo.Author
Any updates on whether this PR will be merged?
Updated it to include tests for typing.
@rbarrois please, take a look. I've added tests for types based on pytest-mypy-plugins.
any news ?
Should stub/stub_batch be typed to return StubObject? Still better than Any. Other than that, having this PR merged would be really useful, as you can't really make use of the type stubs as from the implementation side (and not the stubs file), the factory class doesn't inherit from Generic or define any __class_getitem__ class method
Should
stub/stub_batchbe typed to returnStubObject? Still better thanAny. Other than that, having this PR merged would be really useful, as you can't really make use of the type stubs as from the implementation side (and not the stubs file), the factory class doesn't inherit fromGenericor define any__class_getitem__class method
I'm not sure. StubObject is generic container, and from type-checking perspective it's empty, so you cannot access any attributes.
I'm not sure. StubObject is generic container, and from type-checking perspective it's empty, so you cannot access any attributes.
Yes but at least people would know what object it is, instead of Any currently (as I believe no type checker can infer the return type considering it is making subcalls to _generate)
@Viicos i think it's better to leave it as is, at least for now. This PR is focused on just basic typing support.
After merging this, you can improve typing for StubFactory.
Gentle bump @francoisfreitag considering how many people requested it
I don’t see opposition to merging this work. I offered a small fixes as a PR. Once these fixes are correct, and integrated into this PR, I think we can merge it.
In the meantime, @rbarrois’ opinion is very welcome :)
Oh, I missed that PR. Fixes accepted!
Can you rebase one last time before merging, please? :pray:
Sure, rebased already, but looks like typing tests aren't running in CI.
Almost ready.