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

Annotated with optional meta #4546

Closed
vitalik opened this issue Jun 27, 2023 · 2 comments
Closed

Annotated with optional meta #4546

vitalik opened this issue Jun 27, 2023 · 2 comments
Assignees

Comments

@vitalik
Copy link

vitalik commented Jun 27, 2023

Hello I'm bumping my head trying to develop a custom Annotated class...

Annotated allows to add some metadata to type hint that can be checked at runtime:

from typing import Annotated

some: Annotated[int, 'must be even']

so metadata is always required - but I want to develop a similar type that initialises metadata with some default value:

some: MyAnnotated[int] # <- this must now be equal to Annotated[int, '<default-meta>']

I'm able to make it work with this code:

from typing import Generic, TypeVar, Annotated, Any

T = TypeVar('T')


class MyAnnotated(Generic[T]):
    @classmethod
    def __class_getitem__(cls, param: Any) -> T:
        if isinstance(param, tuple):
            return Annotated[param[0], param[1]]  # type: ignore
        return Annotated[param, '<default-meta>']  # type: ignore


assert MyAnnotated[int, 'my-meta'] == Annotated[int, 'my-meta']
assert MyAnnotated[int] == Annotated[int, '<default-meta>']

this works as expected - but VScode (pylance) does not understand it and cannot add autocompletion:

doesnotwork

while works fine with default Annotated class:

works

is there a way to fool pylance somehow ?

The high level idea is to make some type container that allows to set default:

T = TypeVar("T")
Vec: TypeAlias = Annotated[T, MaxLen(10)]


v1: Vec[int]              # <-- will have meta max-len = 10
v2: Vec[int, MaxLen(20))  # <-- will have meta max-len = 20 - but this example fails with validation error
@rchiodo
Copy link
Contributor

rchiodo commented Jun 27, 2023

Thanks for the issue.

I believe what you're asking for isn't possible. Pylance doesn't know that MyAnnotated is the same as Annotation because Annotation is treated specially. Internally Pylance (actually Pyright in this case) just treats 'Annotated' as the same thing as the first type argument and ignores everything else. It doesn't do any analysis of other classes to see if they're behaving like Annotated which is what I believe would be necessary here to get the completions to work.

I think your only resolution (if you want to do this in Pylance) is to :

  • Use Annotated everywhere and just provide the default arguments.
  • Use your custom MyAnnotated but then lose completions and type information from the point of view of Pylance.

You might try asking on the typing forums to see if there's perhaps another alternative to your MyAnnotated idea.
https://discuss.python.org/tag/typing
https://github.com/python/typing/discussions

@rchiodo rchiodo closed this as completed Jun 27, 2023
@erictraut
Copy link
Contributor

Yes, what Rich said is correct. typing.Annotated is a special form that requires special handling inside of a type checker. You can't create your own version of Annotated with similar properties without extending the type system. I recommend building on Annotated rather than trying to replace it with something custom. For example, you could use some sentinel value to represent "default value".

some: Annotated[int, META_DEFAULT]

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

No branches or pull requests

3 participants