8000 Unpack PEP 695 type aliases if using the `Annotated` form by Viicos · Pull Request #11109 · pydantic/pydantic · GitHub
[go: up one dir, main page]

Skip to content

Unpack PEP 695 type aliases if using the Annotated form #11109

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

Merged
merged 4 commits into from
Dec 27, 2024
Merged

Conversation

Viicos
Copy link
Member
@Viicos Viicos commented Dec 13, 2024

Change Summary

Fixes #6352
Fixes #10219

This PR also makes a first step in refactoring the FieldInfo class (see #11122), at least for the from_annotation constructor method. The method logic is alsmost untouched, it was just adapted to use the new _unpack_annotated utility function (also some variables had to be renamed) and comments were added to better describe the logic.

The from_annotated_attribute should also be updated, but this is left for #11122.

Related issue number

Checklist

  • The pull request title is a good summary of the changes - it will be used in the changelog
  • Unit tests for the changes exist
  • Tests pass on CI
  • Documentation reflects the changes where applicable
  • My PR is ready to review, please add a comment including the phrase "please review" to assign reviewers

@github-actions github-actions bot added the relnotes-fix Used for bugfixes. label Dec 13, 2024
Copy link
cloudflare-workers-and-pages bot commented Dec 13, 2024

Deploying pydantic-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 848d3ee
Status: ✅  Deploy successful!
Preview URL: https://011878fd.pydantic-docs.pages.dev
Branch Preview URL: https://fields-pep695.pydantic-docs.pages.dev

View logs

Copy link
codspeed-hq bot commented Dec 13, 2024

CodSpeed Performance Report

Merging #11109 will not alter performance

Comparing fields-pep695 (848d3ee) with main (aea47de)

Summary

✅ 46 untouched benchmarks

Copy link
Contributor
github-actions bot commented Dec 13, 2024

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  pydantic
  fields.py
  pydantic/_internal
  _generate_schema.py 1981, 1983
  _typing_extra.py 174-178, 195-196
Project Total  

This report was generated by python-coverage-comment-action

@Viicos Viicos force-pushed the fields-pep695 branch 2 times, most recently from aed47cc to ec8f53b Compare December 14, 2024 18:31
@Viicos Viicos changed the title Eagerly evaluate type aliases if annotated Eagerly evaluate PEP 695type aliases if using the Annotated form Dec 14, 2024
@Viicos Viicos changed the title Eagerly evaluate PEP 695type aliases if using the Annotated form Eagerly evaluate PEP 695 type aliases if using the Annotated form Dec 14, 2024
@Viicos Viicos marked this pull request as ready for review December 14, 2024 18:36
@Viicos Viicos changed the title Eagerly evaluate PEP 695 type aliases if using the Annotated form Unpack PEP 695 type aliases if using the Annotated form during fields collection Dec 14, 2024
Comment on lines 405 to 407
# 2. Check if the annotation is an `Annotated` form.
# In this case, `annotation` will be the annotated type:
annotation, metadata = _unpack_annotated(annotation)
Copy link
Member Author

Choose a reason for hiding this comment

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

This replaces:

if _typing_extra.is_annotated(annotation):
    first_arg, *extra_args = typing_extensions.get_args(annotation)

if metadata == [], it means _typing_extra.is_annotated(annotation) == False.

@@ -314,28 +314,14 @@ def test_recursive_generic_type_alias_annotated_defs() -> None:
}


@pytest.mark.xfail(reason='description is currently dropped')
def test_field() -> None:
Copy link
Member Author

Choose a reason for hiding this comment

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

Now works, was moved below

Comment on lines +1976 to +1978
# Ideally, we should delegate all this to `_typing_extra.unpack_annotated`, e.g.:
# `typ, annotations = _typing_extra.unpack_annotated(annotated_type); schema = self.apply_annotations(...)`
# if it was able to use a `NsResolver`. But because `unpack_annotated` is also used
# when constructing `FieldInfo` instances (where we don't have access to a `NsResolver`),
# the implementation of the function does *not* resolve forward annotations. This could
# be solved by calling `unpack_annotated` directly inside `collect_model_fields`.
# For now, we at least resolve the annotated type if it is a forward ref, but note that
# unexpected results will happen if you have something like `Annotated[Alias, ...]` and
# `Alias` is a PEP 695 type alias containing forward references.
Copy link
Member Author

Choose a reason for hiding this comment

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

See test_nested_annotated_with_type_aliases_and_forward_ref showing an example of when it fails.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeesh. This comment is helpful, as this logic is pretty specialized and complicated. Thanks for including.

I honestly don't know if my mind is fully wrapped around this yet.

@Vii
8000
cos Viicos changed the title Unpack PEP 695 type aliases if using the Annotated form during fields collection Unpack PEP 695 type aliases if using the Annotated form Dec 17, 2024
@Viicos Viicos added the third-party-tests Add this label on a PR to trigger 3rd party tests label Dec 20, 2024
Copy link
Contributor
@sydney-runkle sydney-runkle left a comment

Choose a reason for hiding this comment

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

I'm very impressed with your understanding of these nuances and edge cases here.

I've left a few questions / comments. Generally, looks good to me. Happy to do another quick pass after you've looked at feedback.

pydantic/fields.py Show resolved Hide resolved
Comment on lines +1976 to +1978
# Ideally, we should delegate all this to `_typing_extra.unpack_annotated`, e.g.:
# `typ, annotations = _typing_extra.unpack_annotated(annotated_type); schema = self.apply_annotations(...)`
# if it was able to use a `NsResolver`. But because `unpack_annotated` is also used
# when constructing `FieldInfo` instances (where we don't have access to a `NsResolver`),
# the implementation of the function does *not* resolve forward annotations. This could
# be solved by calling `unpack_annotated` directly inside `collect_model_fields`.
# For now, we at least resolve the annotated type if it is a forward ref, but note that
# unexpected results will happen if you have something like `Annotated[Alias, ...]` and
# `Alias` is a PEP 695 type alias containing forward references.
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeesh. This comment is helpful, as this logic is pretty specialized and complicated. Thanks for including.

I honestly don't know if my mind is fully wrapped around this yet.

@sydney-runkle
Copy link
Contributor

I feel ok approving this once you add new changes because:

  • Third party tests are passing
  • Existing tests are passing
  • You've added new tests showing extended support

Copy link
Contributor
@sydney-runkle sydney-runkle left a comment

Choose a reason for hiding this comment

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

Feedback commit looks good. Thanks for digging into this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes-fix Used for bugfixes. third-party-tests Add this label on a PR to trigger 3rd party tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

defaulting behavior of Field inside of TypeAliasType not working when used inside discriminated union Field doesn't play well with TypeAliasType
2 participants
0