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

Fix validation_alias behavior with model_construct for AliasChoices and AliasPath #9223

Merged
merged 7 commits into from
Apr 12, 2024

Conversation

sydney-runkle
Copy link
Member

@sydney-runkle sydney-runkle commented Apr 12, 2024

Fix #9216
Fix #9220

Initially introduced in #9144 because we forgot to account for AliasPath and AliasChoices validation aliases!

Selected Reviewer: @adriangb

@sydney-runkle sydney-runkle added the relnotes-fix Used for bugfixes. label Apr 12, 2024
Copy link

cloudflare-workers-and-pages bot commented Apr 12, 2024

Deploying pydantic-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: c1d585f
Status: ✅  Deploy successful!
Preview URL: https://9d295dfb.pydantic-docs2.pages.dev
Branch Preview URL: https://full-alias-fix.pydantic-docs2.pages.dev

View logs

Copy link

codspeed-hq bot commented Apr 12, 2024

CodSpeed Performance Report

Merging #9223 will not alter performance

Comparing full_alias_fix (c1d585f) with main (59eace3)

Summary

✅ 13 untouched benchmarks

@sydney-runkle
Copy link
Member Author

Please review

@dmontagu
Copy link
Contributor

dmontagu commented Apr 12, 2024

One potential issue with this approach — the following code errors for normal validation:

from pydantic import BaseModel, AliasPath, Field


class MyModel(BaseModel):
    x: str = Field(alias=AliasPath('y', 1))

print(MyModel(y=['abc', 'def']))

print(MyModel(y='abc'))
"""
y.1
  Field required [type=missing, input_value={'y': 'abc'}, input_type=dict]
"""

and if you add a default, you get the default:

from pydantic import BaseModel, AliasPath, Field


class MyModel(BaseModel):
    x: str = Field(default='xyz', alias=AliasPath('y', 1))

print(MyModel(y=['abc', 'def']))
#> x='def'

print(MyModel(y='abc'))
#> x='xyz'

However, with your current implementation, if you use model_construct I believe you'd end up with:

from pydantic import BaseModel, AliasPath, Field


class MyModel(BaseModel):
    x: str = Field(default='xyz', alias=AliasPath('y', 1))

print(MyModel.model_construct(y=['abc', 'def']))
#> x='def'  (as expected)

print(MyModel.model_construct(y='abc'))
#> x='b'  (not expected)

Not sure if this is a blocking-level problem, or if it's worth the overhead it would add to prevent this misbehavior.

@sydney-runkle
Copy link
Member Author

Just added an isinstance(v, str) check to prevent that behavior, which now results in:

from pydantic import BaseModel, AliasPath, Field


class MyModel(BaseModel):
    x: str = Field(default='xyz', validation_alias=AliasPath('y', 1))

print(MyModel.model_construct(y=['abc', 'def']))
#> x='def'  (as expected)

print(MyModel.model_construct(y='abc'))
#> x='xyz'  (as expected)

@sydney-runkle sydney-runkle changed the title 2.7 alias fix Fix validation_alias behavior with model_construct for AliasChoices and AliasPath Apr 12, 2024
@sydney-runkle sydney-runkle enabled auto-merge (squash) April 12, 2024 20:13
@sydney-runkle sydney-runkle merged commit 6aab43e into main Apr 12, 2024
53 checks passed
@sydney-runkle sydney-runkle deleted the full_alias_fix branch April 12, 2024 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants