-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Add support for Pydantic models in stubgen
#19095
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
base: master
Are you sure you want to change the base?
Conversation
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
stubgen
Hello @JelleZijlstra! Hope you're doing well 🙂 |
Hello @hauntsaninja! Hope you're doing well! |
Hi @sobolevn! You're my last hope 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! One main comment :)
test-data/unit/stubgen.test
Outdated
|
||
class User(BaseUser): | ||
name: str | ||
email: str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
email: str | |
email: str = '@' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an issue connected with this change. Currently, the code only sets processing_pydantic_model = True
when the direct base class is pydantic.BaseModel
, but it doesn't handle cases where a class inherits from another class that inherits from pydantic.BaseModel
. I tried a few ideas but they aren't working. Could you please give me a clue how to tackle the problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @sobolevn, do you have any idea how to detect the indirect inheritance from pydantic.BaseModel? Besides that, do you know why ellipses aren't propagated for the attributes with default values in general? I guess it might be relevant for all classes, not only pydantic descendants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is "indirect inheritance"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's not the correct term, but I mean that if we have:
class BaseUser(BaseModel):
pass
class User(BaseUser):
pass
BaseUser directly inherited from BaseModel (and base_type_expr contains this info), whereas User indirectly inherited from BaseModel (and base_type_expr doesn't contain info about BaseModel).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can inspect the mro
of a TypeInfo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @sobolevn! I pushed the changes with Pydantic inheritance detection via mro
. Unfortunately, mro
contains the following list: [<TypeInfo main.User>, <TypeInfo main.BaseUser>, <TypeInfo builtins.object>]
and no pydantic.BaseModel
. Could you help me to identify the reason?
name: str | ||
email: str | ||
|
||
[case testPydanticModelWithMethods] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just add some methods to existing models. Let's reduce the amount of tests without reducing test features.
@@ -887,6 +882,20 @@ def visit_class_def(self, o: ClassDef) -> None: | |||
self.processing_enum = False | |||
self.processing_pydantic_model = False | |||
|
|||
def _inherits_from_pydantic_basemodel(self, class_def: ClassDef) -> bool: | |||
"""Check if a class directly or indirectly inherits from pydantic.BaseModel""" | |||
for base_type_expr in class_def.base_type_exprs: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: why do we need this branch?
This PR adds support for generating stubs for Pydantic models in
stubgen
.Changes
pydantic.BaseModel
directly or indirectlyFixes #16968