Skip to content
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

Inference of typing.Annotated #1747

Open
dsalisbury opened this issue Feb 8, 2021 · 3 comments
Open

Inference of typing.Annotated #1747

dsalisbury opened this issue Feb 8, 2021 · 3 comments
Labels

Comments

@dsalisbury
Copy link

Hey!

I've got a project where I'm looking at using the Annotated type annotation which was new in Python 3.9 (and backported through typing_extensions).

typing.Annotated

A type, introduced in PEP 593 (Flexible function and variable annotations), to decorate existing types with context-specific metadata (possibly multiple pieces of it, as Annotated is variadic). Specifically, a type T can be annotated with metadata x via the typehint Annotated[T, x]. This metadata can be used for either static analysis or at runtime. If a library (or tool) encounters a typehint Annotated[T, x] and has no special logic for metadata x, it should ignore it and simply treat the type as T.

I'd expect Jedi to take the naive route and go with "simply treat the type as T". However it's not something which Jedi handles at present as I've confirmed with a fresh clone of the repo today.

How might I go about adding support for this in Jedi? I'm new to this codebase so some pointers would be appreciated.

Or is this even a Jedi thing in the first place? is something else missing a definition about Annotated?

I was looking at how to implement it and ended up starting with a basic test which fails as expected. Does this look right as a starting point?

from typing import Annotated

# This is just a dummy and very meaningless thing to use with to the Annotated
# type hint
class Foo:
    pass

class A:
    pass


def annotated_function_params(
    basic: Annotated[str, Foo()],
    obj: A,
    annotated_obj: Annotated[A, Foo()],
):
    #? str
    basic

    #? A()
    obj

    #? A()
    annotated_obj

The first and third tests there fail as expected with this sort of message:

E       AssertionError:
E         Test <IntegrationTestCase: /src/test/completion/pep0593_annotations.py:24 '    annotated_obj'> failed.
E         actual  =
E             set()
E         desired =
E             {'completion.pep0593_annotations.A()'}
E
E       assert set() == {'completion....otations.A()'}
E         Extra items in the right set:
E         'completion.pep0593_annotations.A()'
E         Full diff:
E         - {'completion.pep0593_annotations.A()'}
E         + set()
@davidhalter
Copy link
Owner

davidhalter commented Feb 8, 2021

I'm pretty sure this is not handled yet. Want to try to fix it? I'm happy to assist.

The right place to work on this is definitely jedi/inference/gradual/typing.py. It's probably a really small fix (20 lines). The hard part is to understand what you need to do.

@asford
Copy link
Contributor

asford commented Apr 9, 2021

@davidhalter Any hints on where to start in jedi/inference/gradual/typing.py?

I think the intended behavior would be to just return the type of the first parameter to the Annotated generic. Would this be treated the sameway as ClassVar?

elif string_name == 'ClassVar':
# For now don't do anything here, ClassVars are always used.
return self._generics_manager[0].execute_annotation()

@davidhalter
Copy link
Owner

I think the intended behavior would be to just return the type of the first parameter to the Annotated generic. Would this be treated the sameway as ClassVar?

Oh yeah, good find! It's pretty much that I guess. Feel free to create a PR for it :)

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

No branches or pull requests

3 participants