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

How to alias Annotated to a subscriptable type #779

Open
FFY00 opened this issue Jan 19, 2021 · 3 comments
Open

How to alias Annotated to a subscriptable type #779

FFY00 opened this issue Jan 19, 2021 · 3 comments
Labels
topic: feature Discussions about new features for Python's type annotations

Comments

@FFY00
Copy link
Member

FFY00 commented Jan 19, 2021

Hi, I want to create a type alias that simply wraps a tuple into Annotated.

PEP 593

I want to be able to write

SpecialReturn[int, bool, str]

And get

Annotated[Tuple[int, bool, str], 'special return!']

Among other things, I've tried:

class SpecialReturn():
    def __class_getitem__(self, params: Tuple[Any, ...]) -> Tuple[Any, ...]:
        return typing.cast(
            Tuple[Any, ...],
            _typing.Annotated[
                typing.Tuple.__getitem__(params),
                'multiple_return',
            ]
        )

Which mypy is happy with the declaration, but not using it:

import typing

from typing import Annotated, Any, Tuple


class SpecialReturn():
    def __class_getitem__(self, params: Tuple[Any, ...]) -> Tuple[Any, ...]:
        return typing.cast(
            Tuple[Any, ...],
            Annotated[
                typing.Tuple.__getitem__(params),
                'multiple_return',
            ]
        )


def test() -> SpecialReturn[int, int]:
    return 1, 2
test8.py:17: error: "SpecialReturn" expects no type arguments, but 2 given
test8.py:18: error: Incompatible return value type (got "Tuple[int, int]", expected "SpecialReturn")

Which happens because I guess mypy does not evaluate the type annotation, it just treats SpecialReturn as a separate type. I am not sure what is the reasoning behind this, but I assume there it makes sense in some way(?).

So, is there any alternative? How do achieve this? I essentially want to alias Tuple and be able to find out at runtime if the type is a normal tuple or my special one.

My first jab at this, and what I think makes most sense to a Python developer is the following

from typing import Tuple


class SpecialReturn(Tuple):
    pass


def test() -> SpecialReturn[int, int]:
    return 1, 2

But mypy can't handle it either:

test.py:4: error: Missing type parameters for generic type "Tuple"
test.py:8: error: "SpecialReturn" expects no type arguments, but 2 given
test.py:9: error: Incompatible return value type (got "Tuple[int, int]", expected "SpecialReturn")

I was thinking maybe something like this was possible with Annotated, but it seems not.

@FFY00
Copy link
Member Author

FFY00 commented Jan 19, 2021

I have also tried using generics in the past, but they also don't seem suitable, as I want the fields that go into the type to be anything that Tuple supports.

@wyfo
Copy link

wyfo commented Jan 21, 2021

__class_getitem__ is a dynamic thing; I think static checkers will never evaluate it. In the current state Python typing, I don't see a way to achieve what you want.

In fact, you need to parametrize a tuple, which is variadic, so you need to create yourself a variadic type, and that's not possible for now. You can take a look at #193, but this is a complicated issue, opened 4 years ago, still without resolution.

A common solution of this variadic issue is to declare one type by "variation", like this:

SpecialReturn = Annotated[T, ...]
SpecialReturn1 = SpecialReturn[tuple[T1]]
SpecialReturn2 = SpecialReturn[tuple[T1, T2]]
SpecialReturn3 = SpecialReturn[tuple[T1, T2, T3]]
SpecialReturn4 = SpecialReturn[tuple[T1, T2, T3, T4]]
… # do you need more than 4

But I agree it's not so nice.

@mrahtz
Copy link

mrahtz commented Feb 20, 2021

@FFY00 @wyfo I noticed you referenced python/typing#193 on variadic generics in this thread. Heads up that we've been working on a draft of a PEP for this in PEP 646. If this is something you still care about, take a read and let us know any feedback in this thread in typing-sig. Thanks!

@srittau srittau added the topic: feature Discussions about new features for Python's type annotations label Nov 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: feature Discussions about new features for Python's type annotations
Projects
None yet
Development

No branches or pull requests

4 participants