Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

FixNameError when usingvalidate_call with PEP 695 on a class#10380

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
sydney-runkle merged 9 commits intopydantic:mainfromkc0506:fix-10150
Sep 12, 2024

Conversation

kc0506
Copy link
Contributor

@kc0506kc0506 commentedSep 11, 2024
edited
Loading

Change Summary

This PR fixes theNameError whenfrom __future__ import annotations and we callvalidate_call inside a class definition with PEP 695:

from __future__importannotationsclassA[T]:@validate_call(validate_return=True)deff(self,a:T)->T:returnstr(a)

However, callingvalidate_call in nested scopes will still throwNameError. This is probably due toparent_frame_namespace. Example:

from __future__importannotationsfrompydanticimportvalidate_callclassA[T]:defg(self):@validate_call(validate_return=True)definner(a:T)->T: ...A().g()# throws because we can only get the ns of `g`, not `A` when calling `@validate_call`

Related issue number

fix#10150

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-actionsgithub-actionsbot added the relnotes-fixUsed for bugfixes. labelSep 11, 2024
@codspeed-hqCodSpeed HQ
Copy link

codspeed-hqbot commentedSep 11, 2024
edited
Loading

CodSpeed Performance Report

Merging#10380 willnot alter performance

Comparingkc0506:fix-10150 (b42288d) withmain (07beaff)

Summary

✅ 49 untouched benchmarks

@github-actionsGitHub Actions
Copy link
Contributor

github-actionsbot commentedSep 11, 2024
edited
Loading

Coverage report

This PR does not seem to contain any modification to coverable code.

Copy link
Contributor

@sydney-runklesydney-runkle left a comment

Choose a reason for hiding this comment

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

LGTM overall, just a few change requests :).

@pydantic-hookypydantic-hookybot added awaiting author revisionawaiting changes from the PR author labelsSep 12, 2024
Copy link
Contributor

@sydney-runklesydney-runkle left a comment

Choose a reason for hiding this comment

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

Nice work, thanks!!

@sydney-runklesydney-runkleenabled auto-merge (squash)September 12, 2024 15:44
@sydney-runklesydney-runkle merged commit899ff2c intopydantic:mainSep 12, 2024
58 checks passed
@kc0506
Copy link
ContributorAuthor

kc0506 commentedSep 13, 2024
edited
Loading

@sydney-runkle I think the nested scope issues here are different from the case ofTypeAdapter .
Take this code for example:

from __future__importannotationsclassA[T:int](BaseModel):defg1(self):returnTypeAdapter(list[T])defg2(self):@validate_calldeff()->T: ...

When callingTypeAdapter, the Python bytecode actuallyuseT, soT will be recognized inside the closure when compilingg1's code object. ThusT will becopied into locals at runtime wheng1 is called.

On the other hand, theT insideg2 is just purestr, not a reference toT, so from the viewpoint of compiler,T is not evenused byg2. Therefore at runtime, the local namespace ofg2 will not containT, which means there is no way to accessT inside@validate_call.

So currently I guess the best we could do is to make sure things work withoutfrom __future__ import annotations, and perhaps note the issue somewhere of the docs. I hope this make sense for you.

@sydney-runkle
Copy link
Contributor

Gotcha.

My suggestion was that we could add a_parent_depth argument tovalidate_call to control how deep we look in theparent_frame_namespace, which might resolve the original issue you mentioned. Maybe not though, I haven't tried locally.

kc0506 reacted with eyes emoji

@kc0506
Copy link
ContributorAuthor

kc0506 commentedSep 13, 2024
edited
Loading

importinspectimportsysfrompydantic._internalimport_typing_extra# analogy to `validate_call`, we want to access `a` in this functiondefapi():# ! `f` is NOT in stack# print([f.function for f in inspect.stack()])  # ['api', 'g', '<module>']# print(sys._getframe(1).f_code.co_name)  # 'g'# print(sys._getframe(2).f_code.co_name)  # '<module>'# parent_depth should add 1 because `parent_frame_namespace` is pushed to call stackprint('ns of g:',_typing_extra.parent_frame_namespace(parent_depth=2))deff():a=1defg1():api()defg2():aapi()returng1,g2g1,g2=f()g1()# ns of g: {}g2()# ns of g: {'a': 1}

Here is a simple demo. My point is that by the timeapi is called,f is not in the stack anymore. So we can not finda in the namespace no matter how deep we look in parent frames, unless it is caught by closure, as the case ofg2. This behavior should be the same forclass definition.

sydney-runkle reacted with heart emoji

@kc0506kc0506 deleted the fix-10150 branchOctober 14, 2024 10:05
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@sydney-runklesydney-runklesydney-runkle approved these changes

Assignees

@kc0506kc0506

Labels
awaiting author revisionawaiting changes from the PR authorrelnotes-fixUsed for bugfixes.
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

"NameError: name 'T' is not defined" when using "from __future__ import annotations" with generic function
2 participants
@kc0506@sydney-runkle

[8]ページ先頭

©2009-2025 Movatter.jp