Skip to content
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

Same model returned by pydantic_model_creator calls with different arguments #1741

Merged

Conversation

henadzit
Copy link
Contributor

@henadzit henadzit commented Oct 16, 2024

Description

This PR fixes the issue where calling pydantic_model_creator multiple times with different arguments without specifying a name might return the same model due to caching (_MODEL_INDEX in creator.py). The example below demonstrates the issue.

from tortoise import fields
from tortoise.contrib.pydantic import pydantic_model_creator
from tortoise.models import Model


class People(Model):
    id = fields.IntField(pk=True)
    created_at = fields.DatetimeField(auto_now_add=True)
    modified_at = fields.DatetimeField(auto_now=True)

    first_name = fields.CharField(max_length=50)
    last_name = fields.CharField(max_length=50)


Person = pydantic_model_creator(People)
PersonIn = pydantic_model_creator(People, exclude_readonly=True)

print(list(Person.model_fields))  
# [id, created_at, modified_at, first_name_last_name]
print(list(PersonIn.model_fields))  
# [id, created_at, modified_at, first_name_last_name] 
# However, it should be ['first_name', 'last_name'] because of exclude_readonly=True

print(Person is PersonIn)  
# True (!)

This issues affects the models that have no backward or forward reference to any other model.

This PR:

  • Makes pydantic_model_creator to create verbatim names for "root" models even if they do not have relations
  • Adds the exclude_readonly to the hash used for naming unnamed models so pydantic_model_creator(People) and pydantic_model_creator(People, exclude_readonly=True)

Motivation and Context

The issues that will be fixed by this PR:

There was an attempt to solve this issue previously but it was never merged. The approach used does not seem to work anymore.

How Has This Been Tested?

  • Tested the snippets from the issues above
  • Added unit tests

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added the changelog accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@henadzit
Copy link
Contributor Author

Hey @waketzheng @waketzheng, any chance you can review this PR? Please let me know if more information or more tests are required! Thanks!

@coveralls
Copy link

Pull Request Test Coverage Report for Build 11407291191

Details

  • 2 of 2 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.008%) to 89.021%

Totals Coverage Status
Change from base Build 11323175489: 0.008%
Covered Lines: 5980
Relevant Lines: 6603

💛 - Coveralls

Copy link
Member

@abondar abondar left a comment

Choose a reason for hiding this comment

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

Thank you for venturing into pydantic model created, it's one of more convoluted pieces of code there :)

@abondar abondar merged commit 785c9ad into tortoise:develop Oct 21, 2024
7 checks passed
@henadzit
Copy link
Contributor Author

Thank you for venturing into pydantic model created, it's one of more convoluted pieces of code there :)

Thank you for maintaining tortoise-orm! I'm glad to be of help!

There was a PR (#735) a while ago that was partially solving the issue but never got merged, I think it can be closed now.

markus-96 added a commit to markus-96/tortoise-orm that referenced this pull request Oct 23, 2024
abondar pushed a commit that referenced this pull request Nov 17, 2024
* naming is not working

* naming and description

* naming is not working

* naming and description

* include improvements from #1741

* remove print statements

* i should learn git better...

* type hints, recursion protector, naming, ....

should be ready for review

* unused import statements...

* test_early_init.py: naming of $defs changed

* move dataclasses to a dedicated place

* python 3.8 and 3.9: typing

* test computed fields, remove own PydanticMeta class

* remove print statements from tests

* re-add pydantic_model_creator docstring

it got lost during refactoring

* remove _stack from pydantic_model_creator

this is now handled by PydanticModelCreator

* make some methods private

* slim down dataclasses to only include necessary information

* remove unused imports, satisfy mypy

* add type annotation for ``from_pydantic_meta``

* better indexing of pydantic models

* remove dataclasses for field descriptions

pydantic_model_creator now accesses the fields directly

* remove forgotten line of #1465

* include optional in hashed value

* move dataclasses.py to descriptions.py

* stupid unused import.

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