Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix missing recursive_guard parameter in Pydantic v1 for python 3.12.4+ #9611

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

Closed
wants to merge 5 commits into from

Conversation

ellyx13
Copy link

@ellyx13 ellyx13 commented Jun 8, 2024

Change Summary

I add args recursive guard=set() when calling evaluate function because in python 3.12 they don't add default value for this params. You can see that here.

While waiting for this merge request to be accepted, you can quickly fix it by using python version 3.12.3

Related issue number

fix #9609 and fix #9607

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

Skip change file check

Copy link

codspeed-hq bot commented Jun 8, 2024

CodSpeed Performance Report

Merging #9611 will not alter performance

Comparing ellyx13:fix/pydantic/v1/typing (68458d0) with main (8333bd5)

Summary

✅ 13 untouched benchmarks

Comment on lines 66 to 71
else:
def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
# For 3.12.4+ provide a default `recursive_guard` to resolve:
# TypeError: ForwardRef._evaluate() missing 1 required keyword-only argument: 'recursive_guard'
return cast(Any, type_)._evaluate(globalns, localns, set(), recursive_guard=set())

Copy link

@vfazio vfazio Jun 8, 2024

Choose a reason for hiding this comment

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

I think I made a mistake when i glanced at the code earlier. That's what i get when i do things in a rush.

Python 3.12.4 has this commit:

vfazio@Zephyrus:~/development/cpython$ git describe --contains 5430f614371530aab1178b3b610add4bf54c383e
v3.12.4~194

Which is: python/cpython#118104

Which changed the function signature of ForwardRef._evaluate to force recursive_guard to be a kwarg

def _evaluate(self, globalns, localns, type_params=None, *, recursive_guard):
>>> inspect.signature(typing.ForwardRef._evaluate).parameters['recursive_guard'].kind
<_ParameterKind.KEYWORD_ONLY: 3>

The fixup should maybe be:

if sys.version_info < (3, 9):

    def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
        return type_._evaluate(globalns, localns)

else:
    def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
        # Even though it is the right signature for python 3.9, mypy complains with
        # `error: Too many arguments for "_evaluate" of "ForwardRef"` hence the cast...
        # Note 3.13/3.12.4+ made `recursive_guard` a kwarg, so name it explicitly to avoid:
        # TypeError: ForwardRef._evaluate() missing 1 required keyword-only argument: 'recursive_guard'
        return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())

The syntax should work on previous versions (pre 3.12.4/3.13) and also work for the new kwarg status.

The extra set() is unnecessary and is actually overwriting the default value for type_params.

Anyway, totally untested, but my thoughts. I am not a maintainer, so this should also be taken with a modest amount of skepticism

Copy link
Author

Choose a reason for hiding this comment

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

I think I made a mistake when i glanced at the code earlier. That's what i get when i do things in a rush.

Python 3.12.4 has this commit:

vfazio@Zephyrus:~/development/cpython$ git describe --contains 5430f614371530aab1178b3b610add4bf54c383e
v3.12.4~194

Which is: python/cpython#118104

Which changed the function signature of ForwardRef._evaluate to force recursive_guard to be a kwarg

def _evaluate(self, globalns, localns, type_params=None, *, recursive_guard):
>>> inspect.signature(typing.ForwardRef._evaluate).parameters['recursive_guard'].kind
<_ParameterKind.KEYWORD_ONLY: 3>

The fixup should maybe be:

if sys.version_info < (3, 9):

    def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
        return type_._evaluate(globalns, localns)

else:
    def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any:
        # Even though it is the right signature for python 3.9, mypy complains with
        # `error: Too many arguments for "_evaluate" of "ForwardRef"` hence the cast...
        # Note 3.13/3.12.4+ made `recursive_guard` a kwarg, so name it explicitly to avoid:
        # TypeError: ForwardRef._evaluate() missing 1 required keyword-only argument: 'recursive_guard'
        return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())

The syntax should work on previous versions (pre 3.12.4/3.13) and also work for the new kwarg status.

The extra set() is unnecessary and is actually overwriting the default value for type_params.

Anyway, totally untested, but my thoughts

Is it just that I need to run tests on all python versions to make sure it's correct? Can you guide me, because I really want to fix this error, thank you.

Schamschula added a commit to macports/macports-ports that referenced this pull request Jun 9, 2024
@sydney-runkle sydney-runkle changed the base branch from main to 1.10.X-fixes June 9, 2024 20:36
@sydney-runkle sydney-runkle changed the base branch from 1.10.X-fixes to main June 9, 2024 20:36
@sydney-runkle
Copy link
Contributor

@ellyx13,

This change looks great. Could you please create a branch from v1.10.X-fixes, add this change, then open a PR against v1.10.X fixes instead? We'll want to merge it there to get it into our next V1 release, and we'll pull that into our next V2 release as well under the V1 namespace.

@vfazio
Copy link

vfazio commented Jun 9, 2024

@ellyx13,

This change looks great. Could you please create a branch from v1.10.X-fixes, add this change, then open a PR against v1.10.X fixes instead? We'll want to merge it there to get it into our next V1 release, and we'll pull that into our next V2 release as well under the V1 namespace.

If this hasn't been done by tomorrow AM, I'll make a PR. This issue is preventing us from taking 3.12.4 so I'd like to see this fixed.

@ellyx13
Copy link
Author

ellyx13 commented Jun 10, 2024

@ellyx13,

This change looks great. Could you please create a branch from v1.10.X-fixes, add this change, then open a PR against v1.10.X fixes instead? We'll want to merge it there to get it into our next V1 release, and we'll pull that into our next V2 release as well under the V1 namespace.

I will do it now. This PR will be closed because I will open a new PR on branch 1.10.X-fixes. Thanks to @sydney-runkle and @vfazio

@allex083
Copy link

HI all, I'm just running into this error: File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/pydantic/v1/typing.py", line 520, in update_field_forward_refs
field.type_ = evaluate_forwardref(field.type_, globalns, localns or None)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/pydantic/v1/typing.py", line 66, in evaluate_forwardref
return cast(Any, type_)._evaluate(globalns, localns, set())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: ForwardRef._evaluate() missing 1 required keyword-only argument: 'recursive_guard'.

pydantic version is 3.6.1 and my Python version is 3.12.4.

How can I fix this error? SOS~~ THANKS

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

Successfully merging this pull request may close these issues.

TypeError: ForwardRef._evaluate() missing 1 required keyword-only argument: 'recursive_guard' Pydantic 1.X doesn't work with Python 3.12.4
4 participants