Skip to content

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

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

teplandr
Copy link

@teplandr teplandr commented May 16, 2025

This PR adds support for generating stubs for Pydantic models in stubgen.

Changes

  • Added detection of classes that inherit from pydantic.BaseModel directly or indirectly
  • Enhanced the stub generation process to add appropriate initializers (= ...) to field annotations in Pydantic models
  • Added comprehensive test cases for different Pydantic model scenarios

Fixes #16968

@teplandr teplandr changed the title Add support for Pydantic models in ASTStubGenerator Add support for Pydantic models in stubgen May 20, 2025
@teplandr teplandr marked this pull request as ready for review May 20, 2025 11:03
@teplandr
Copy link
Author

Hello @JelleZijlstra! Hope you're doing well 🙂
I saw that you recently reviewed PR with stubgen improvements. Could you please take a look at proposed changes?
Thanks in advance!

@teplandr
Copy link
Author

Hello @hauntsaninja! Hope you're doing well!
Could you please review the proposed changes, or suggest someone who can?

@teplandr
Copy link
Author

Hi @sobolevn! You're my last hope 🙂
Could you please review the proposed changes?

Copy link
Member

@sobolevn sobolevn left a 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 :)


class User(BaseUser):
name: str
email: str
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
email: str
email: str = '@'

Copy link
Author

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?

Copy link
Author

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is "indirect inheritance"?

Copy link
Author

@teplandr teplandr Jul 3, 2025

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).

Copy link
Member

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

Copy link
Author

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]
Copy link
Member

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:
Copy link
Member

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrect stub generation for subclasses of pydantic.BaseModel
2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy