-
-
Notifications
You must be signed in to change notification settings - Fork 32k
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -639,28 +639,38 @@ def get_annotations( | |
if eval_str and format != Format.VALUE: | ||
raise ValueError("eval_str=True is only supported with format=Format.VALUE") | ||
|
||
# For VALUE format, we look at __annotations__ directly. | ||
if format != Format.VALUE: | ||
annotate = get_annotate_function(obj) | ||
if annotate is not None: | ||
ann = call_annotate_function(annotate, format, owner=obj) | ||
if not isinstance(ann, dict): | ||
raise ValueError(f"{obj!r}.__annotate__ returned a non-dict") | ||
return dict(ann) | ||
|
||
if isinstance(obj, type): | ||
try: | ||
ann = _BASE_GET_ANNOTATIONS(obj) | ||
except AttributeError: | ||
# For static types, the descriptor raises AttributeError. | ||
return {} | ||
else: | ||
ann = getattr(obj, "__annotations__", None) | ||
if ann is None: | ||
return {} | ||
|
||
if not isinstance(ann, dict): | ||
raise ValueError(f"{obj!r}.__annotations__ is neither a dict nor None") | ||
match format: | ||
case Format.VALUE: | ||
# For VALUE, we only look at __annotations__ | ||
ann = _get_dunder_annotations(obj) | ||
case Format.FORWARDREF: | ||
# For FORWARDREF, we use __annotations__ if it exists | ||
try: | ||
ann = _get_dunder_annotations(obj) | ||
except NameError: | ||
carljm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pass | ||
else: | ||
return dict(ann) | ||
|
||
# But if __annotations__ threw a NameError, we try calling __annotate__ | ||
ann = _get_and_call_annotate(obj, format) | ||
if ann is not None: | ||
return ann | ||
|
||
# If that didn't work either, we have a very weird object: evaluating | ||
# __annotations__ threw NameError and there is no __annotate__. In that case, | ||
# we fall back to trying __annotations__ again. | ||
return dict(_get_dunder_annotations(obj)) | ||
case Format.SOURCE: | ||
# For SOURCE, we try to call __annotate__ | ||
ann = _get_and_call_annotate(obj, format) | ||
if ann is not None: | ||
return ann | ||
# But if we didn't get it, we use __annotations__ instead. | ||
ann = _get_dunder_annotations(obj) | ||
Comment on lines
+669
to
+670
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this right? If we can't get stringified annotations, I would think we'd want to return an empty dict, not fall back to returning non-stringified annotations. (Unless maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just posted #124551 which instead stringifies the annotations we find. |
||
return ann | ||
case _: | ||
raise ValueError(f"Unsupported format {format!r}") | ||
|
||
if not ann: | ||
return {} | ||
|
@@ -725,3 +735,30 @@ def get_annotations( | |
for key, value in ann.items() | ||
} | ||
return return_value | ||
|
||
|
||
def _get_and_call_annotate(obj, format): | ||
annotate = get_annotate_function(obj) | ||
if annotate is not None: | ||
ann = call_annotate_function(annotate, format, owner=obj) | ||
if not isinstance(ann, dict): | ||
raise ValueError(f"{obj!r}.__annotate__ returned a non-dict") | ||
return dict(ann) | ||
return None | ||
|
||
|
||
def _get_dunder_annotations(obj): | ||
if isinstance(obj, type): | ||
try: | ||
ann = _BASE_GET_ANNOTATIONS(obj) | ||
except AttributeError: | ||
# For static types, the descriptor raises AttributeError. | ||
return {} | ||
else: | ||
ann = getattr(obj, "__annotations__", None) | ||
if ann is None: | ||
return {} | ||
|
||
if not isinstance(ann, dict): | ||
raise ValueError(f"{obj!r}.__annotations__ is neither a dict nor None") | ||
return dict(ann) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
gh-119180: Make FORWARDREF format look at __annotations__ first #124479
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