1
0
forked from VimPlug/jedi

Handle generics appearing within quoted return annotations

This ensures that these quoted likely forwards references in
return type annotations behave like their non-quoted equivalents.

I suspect there may be other places which will need similar
adjustments, which may mean that we should push the conversion
a layer closer to the parsing (perhaps in `py__annotations__`?).

One case I know that this doesn't solve (but which likely needs
similar adjustment) is generics in return types of comment-style
annotations. They're less likely and may not be worth supporting
since all supported Python versions can use the in-syntax spelling
for annotations at this point.
This commit is contained in:
Peter Law
2021-07-25 15:29:30 +01:00
parent 6814a7336c
commit 599a1c3ee1
2 changed files with 28 additions and 0 deletions

View File

@@ -222,6 +222,18 @@ def infer_return_types(function, arguments):
match.group(1).strip()
).execute_annotation()
elif annotation.type == 'string':
annotation = _get_forward_reference_node(
context,
context.inference_state.compiled_subprocess.safe_literal_eval(
annotation.value,
),
)
# The forward reference tree has an additional root node ('eval_input')
# that we don't want. Extract the node we do want, that is equivalent to
# the nodes returned by `py__annotations__` for a non-quoted annotation.
annotation = annotation.children[0]
unknown_type_vars = find_unknown_type_vars(context, annotation)
annotation_values = infer_annotation(context, annotation)
if not unknown_type_vars:

View File

@@ -58,6 +58,12 @@ def typed_bound_generic_passthrough(x: TList) -> TList:
return x
# Forward references are more likely with custom types, however this aims to
# test just the handling of the quoted type rather than any other part of the
# machinery.
def typed_quoted_generic_passthrough(x: T) -> 'List[T]':
return [x]
for a in untyped_passthrough(untyped_list_str):
#? str()
@@ -146,6 +152,16 @@ for q in typed_bound_generic_passthrough(typed_list_str):
q
for r in typed_quoted_generic_passthrough("something"):
#? str()
r
for s in typed_quoted_generic_passthrough(42):
#? int()
s
class CustomList(List):
def get_first(self):
return self[0]