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

Implement PEP 585 (Generic builtins and __future__.annotations) #7907

Closed
Starwort opened this issue Nov 8, 2019 · 32 comments
Closed

Implement PEP 585 (Generic builtins and __future__.annotations) #7907

Starwort opened this issue Nov 8, 2019 · 32 comments

Comments

@Starwort
Copy link

Starwort commented Nov 8, 2019

  • Are you reporting a bug, or opening a feature request? Reporting a bug
  • Please insert below the code you are checking with mypy,
    or a mock-up repro if the source is private. We would appreciate if you try to simplify your case to a minimal repro.
from __future__ import annotations
from collections import defaultdict

squares: defaultdict[tuple, int] = defaultdict(lambda: 999999)
  • What is the actual behaviour/output? MyPy tells me "defaultdict" is not subscriptable, use "typing.DefaultDict" instead
  • What is the behaviour/output you expect? MyPy ignores the subscript error (and recognises it as equivalent) because of from __future__ import annotations
  • What is the version of mypy and Python you are using? 0.740 on 3.8.0 (Ubuntu 18.04)
  • No additional MyPy flags
@ilevkivskyi
Copy link
Member

Looks like this should be not hard to support.

@TH3CHARLie
Copy link
Collaborator

@ilevkivskyi I'd like to take a shot to support this and I may need some hints

@ilevkivskyi
Copy link
Member

@TH3CHARLie Sure, you can try this. I think the fix should contain two parts. First, whenever encountering the future import a file, you should set some flag (probably in the semantic analyzer), and second, at the point where the error is generated check for this flag, and suppress the error if it is set.

@JukkaL
Copy link
Collaborator

JukkaL commented Nov 21, 2019

I think that this needs more discussion. Firstly, it seems pretty clear that list[int] is not a valid type, according to PEP 484 and PEP 563. Similarly, dict, set, tuple and frozenset shouldn't be subscriptable, even when using from __future__ import annotations.

However, mypy allows types such as collections.OrderedDict and collections.Iterable to be subscripted, even though they have aliases in typing and this will fail at runtime. For defaultdict and a few others (beyond the built-in collections mentioned above) require the alias in typing to be used.

Some types, such sa queue.Queue, don't have an alias in typing, and mypy allows these to be subcripted even though it doesn't work at runtime. Otherwise it would be impossible to use Queue as a generic type.

The current behavior seems inconsistent, but I'm not sure what's the desired semantics (with or without from __future__ import annotations). Thoughts?

@ilevkivskyi
Copy link
Member

Since the possible runtime failures happen soon and are quite obvious, I would stay on the side of having some false negatives if this removes some false positives (from a user point of view).

I.e. I am fine with unconditionally allowing list[int] if there is the future import.

@JukkaL
Copy link
Collaborator

JukkaL commented Nov 21, 2019

if this removes some false positives (from a user point of view)

In my opinion this not a false positive, since we are only following the spec.

I.e. I am fine with unconditionally allowing list[int] if there is the future import.

I think that this is such as a big change that it deserves a PEP, especially as not supporting this syntax was explicitly mentioned in PEP 563 (if I'm reading it correctly). One of the main points of PEP 484 was that the same annotation syntax would be used by all tools. I think that any new syntax we experiment with should be clearly marked as a non-standard extension, such as through enabling it via mypy_extensions or an opt-in flag. Otherwise there is a risk of user confusion, and if we set an example, it may lower the barrier for other tools to invent their own extensions as well outside the PEP process. (For example, IDEs might complain about our syntax extensions, or start using ~int for optional types, etc.)

A potential way to experiment with this would be to allow list[int] only after from mypy_extensions import list.

@ilevkivskyi
Copy link
Member

In my opinion this not a false positive, since we are only following the spec.

Sure, there is your opinion, but there is also a user opinion. Seriously what is the point of prohibiting list[int] with the future import apart from annoying people? In fact:

  • It works at runtime (in most cases)
  • Mypy already understands it well
  • There is zero ambiguity about what it means
  • Some people expect this to work in mypy
  • Pyre and pytype already accept list[int] (PyCharm doesn't however)
  • It is used in typeshed

IMO the main point of PEP 585 is to actually enable list[int] at runtime. There is big difference between ~int and list[int], the former is indeed an experimental syntax, while the latter is something everyone always wanted but didn't have because of runtime limitations.

Anyway, I am not going to argue about this, I don't think it is something really important.

@JukkaL
Copy link
Collaborator

JukkaL commented Nov 21, 2019

I agree that supporting list[int] etc. could be quite nice. I'll try to find time to write a PEP about this.

@Starwort
Copy link
Author

Since this thread seems stagnant, I'll post this:
PEP 585 is all about parametrisation of standard collections. In fact, it poses this as an example:

from __future__ import annotations

def find(haystack: dict[str, list[int]]) -> int:
    ...

IMO this shows absolute support for parametrising generics in this way, and additionally, this was written in March - so no need to write a new PEP :P

@JukkaL
Copy link
Collaborator

JukkaL commented Jan 6, 2020

PEP 585 hasn't been accepted yet, though. Allowing list[int] (and so on) only in type annotations that aren't evaluated at runtime could be done separately.

@ethanhs
Copy link
Collaborator

ethanhs commented Feb 21, 2020

FWIW, there is an implementation of PEP 585 for CPython python/cpython#18239

I think for now it would be best to just handle PEP 563, and then soon I will write tests for and land PEP 585 support.

@ethanhs
Copy link
Collaborator

ethanhs commented Mar 30, 2020

PEP 585 has been accepted! https://mail.python.org/archives/list/python-dev@python.org/message/HW2NFOEMCVCTAFLBLC3V7MLM6ZNMKP42/

I will start working on the implementation. The summary is:

  • on 3.7+ with future.annotations, "function and variable annotations can parameterize standard collections". I have a list of types that will be made generic here: PEP 585 steps 7-8: Implement repr for GenericAlias gvanrossum/cpython#1 (comment) (if I missed something, please share!)

  • on 3.9+, the above listed should also be usable in contexts such as cast(list[int], obj), and MkList = Callable[[str], list[str]]

@ethanhs ethanhs changed the title MyPy doesn't understand __future__ annotations Implement PEP 585 (Generic builtins and __future__.annotations) Mar 30, 2020
@srittau
Copy link
Contributor

srittau commented Apr 28, 2020

@ethanhs I think generic builtins should also be allowed in quoted annotations (e.g. foo: "dict[str]" in Python 3.5+) and generally in stubs.

TH3CHARLie added a commit that referenced this issue Sep 6, 2020
This PR partially addresses #7907.
@AllanDaemon
Copy link
Contributor

So, It still needs the support for generic builtins for PEP 585, right?

@gvanrossum
Copy link
Member

Yes. Are you volunteering?

@AllanDaemon
Copy link
Contributor

Yes. Are you volunteering?

I wasn't. But I can try (with some help / mentoring / tutoring).

I not used to mypy code base, and I don't know if this could something feasible as a first contribution. I studied compilers in college and read some of mypy's dev documentation, but still a bit clueless about the changes needed. If it's something worth giving a try, I can asking for some tips and directions about this in Gitter or with someone who volunteer to help me.

@gvanrossum
Copy link
Member

I don't think it's a big change to the type checking logic, so you're in luck -- the big job is probably going to be updating tests. But it's not a trivial change either.

The error message we get is error: "list" is not subscriptable, use "typing.List" instead (for various values of list :-). This comes from the function no_subscript_builtin_alias() in mypy/typeanal.py. It is called in a few different places. The key here appears to be the dict nongen_builtins (defined in nodes.py). What happens if we just empty out that dict?

@AllanDaemon
Copy link
Contributor

AllanDaemon commented Sep 17, 2020

I have a doubt about the __future__.annotations handling in Python 3.7 and 3.8.

A code like this in those versions will show the not subscriptable error, as well it fails to run:

li: list[int] = []

But using the postponed evaluation of annotations like this, it should run ok:

    from __future__ import annotations
    li: list[int] = []

But mypy currently doesn't show any error, been in 3.7 or 3.8. With the __future__.annotations, it should not have any problem in runtime, but shouldn't mypy still show the error: "list" is not subscriptable, use "typing.List" instead? Or accepting it in 3.7/3.8 with __future__.annotations is the desired?

I personally would love it, as just using the future import would allow me to use pep 585 in 3.7 and 3.8, but I wonder if mypy should be treating it like before.

About the GenericAlias I think I figure it out, just need more checking and testing.

@gvanrossum
Copy link
Member

I cannot reproduce this. I always see the error. How are you testing it?

@AllanDaemon
Copy link
Contributor

mypy master branch (mypy 0.790+dev.37777b3f52560c6d801e76a2ca58b91f3981f43f) on python 3.9 rc1 (via pyenv).

file: ga.py

n: list[int] = [42]
$ mypy --python-version 3.7 ga.py
ga.py:1: error: "list" is not subscriptable, use "typing.List" instead
Found 1 error in 1 file (checked 1 source file)
$ mypy --python-version 3.8 ga.py
ga.py:1: error: "list" is not subscriptable, use "typing.List" instead
Found 1 error in 1 file (checked 1 source file)
$ mypy --python-version 3.9 ga.py
ga.py:1: error: "list" is not subscriptable, use "typing.List" instead
Found 1 error in 1 file (checked 1 source file)

file gaf.py:

from __future__ import annotations
n: list[int] = [42]
$ mypy --python-version 3.7 gaf.py
Success: no issues found in 1 source file
$ mypy --python-version 3.8 gaf.py
Success: no issues found in 1 source file
$ mypy --python-version 3.9 gaf.py
Success: no issues found in 1 source file

I'm asking because to support the GenricAlias it seems that just an additional clause in the if is enough, but testing it brought this doubt:

in typeanal.py:

            if (fullname in nongen_builtins
                    and t.args and
                    not self.allow_unnormalized and
                    not self.api.is_future_flag_set("annotations") and
                    self.options.python_version < (3, 9)  #added line
                    ):

But if it should give an error also on 3.7/3.8 with future annotations enabled, I should change it. I'll create a fork and PR soon with this.

@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Sep 17, 2020

This is what was implemented in #7963, mentioned above (this hasn't been released yet, which is presumably why Guido can't repro). We want to accept this in 3.7 and 3.8 with future annotations, for the reasons you mention

@AllanDaemon
Copy link
Contributor

We want to accept this in 3.7 and 3.8 with future annotations, for the reasons you mention

great!

What happens if we just empty out that dict?

It will do exactly what is needed. It's used in typeanal and semananal, so the best would be just clearing it up. My doubt now is the right way to do it, because it has to be done depending on the targeted python version.

I thought doing it just after the nongen_builtins definition in nodes.py, but it's module level and executes even before the main.main() parse the options, that is needed to know the target python version.

I could add some extra clauses to the if in semananal and typeanal that uses it, checking the python version, that would be available at that time.

But the better way I could think is just do this in the main function, after processing the options:

    if options.python_version >= (3, 9):
        from mypy.nodes import nongen_builtins
        nongen_builtins.clear()

It seems a bit hackish, but it would do the job well, without messing with taking all the places it could be used and changing some if clauses to become (even) more complex. I just don't know if this fits the project style. Maybe this could be in a better place them main(). But if it's just ok, I will PR it and go to deal with tests.

@gvanrossum
Copy link
Member

Actually I would prefer it if module-level constants were treated as immutable. We have an API that allows people to invoke mypy's main() repeatedly with different arguments, which include the targeted Python version.

(We have one option that for historic reasons has to be global, and we have to do terrible shenanigans to make this work.)

So I think the better approach is to do the version check in each place where nongen_builtins is used, and substitute an empty dict there.

This would also be the approach to do this in earlier versions as long as from __future__ import annotations is in scope -- but then we'd have to check that the usage occurs in an annotation, not in a runtime-visible place like cast(), class inheritance, or type aliases.

@Hubro
Copy link

Hubro commented Oct 8, 2020

Since this issue is still open, does that mean that mypy doesn't support PEP 585 yet?

@ruohola
Copy link

ruohola commented Oct 8, 2020

@Hubro Yes, that's the case:

$ echo 'foo: list[str]' > test.py && python3 -m mypy test.py
test.py:1: error: "list" is not subscriptable, use "typing.List" instead
Found 1 error in 1 file (checked 1 source file)
$ python3 --version; python3 -m mypy --version
Python 3.9.0
mypy 0.782

@dpinol
Copy link

dpinol commented Oct 23, 2020

from typing import OrderedDict, Dict
  
def f1(self, kk: OrderedDict[int, None]) -> None:
        pass

def f2(self, kk: Dict[int, None]) -> None:
        pass

This complains with the OrderedDict, but works with Dict
kk.py:3: error: Variable "typing.OrderedDict" is not valid as a type

@antonagestam
Copy link
Contributor

@dpinol Documentation states "Deprecated since version 3.9: collections.OrderedDict now supports []. See PEP 585.". You should use from collections import OrderedDict. Not sure that this is relevant to this issue.

@dpinol
Copy link

dpinol commented Oct 23, 2020

right thanks!

@AllanDaemon
Copy link
Contributor

AllanDaemon commented Oct 25, 2020

I was rechecking the pep585 and I noticed that there are a few things that are missing for full pep585 support, like the deprecations warnings. So I did a list of all tasks that should and was done:

  • Implement import future.annotations
  • Implement support for generic alias (WIP)
  • Implement consistently the right reveal_type() for all those types (MAYBE)
  • Generate warnings of deprecation for those types

For the support for generic alias, the type collections.abc.MappingView is not working, and tuple has some rough edge cases (more about this later). The reveal_type() may needs fix for tuple and type and others. And lastly, it's just the deprecation warnings that are missing.

I made a table with all the symbols cited in the PEP 585 with the information. Working means that you can use it without generating error warnings and getting the right type. It's based on my PR (#9564) that implements this. Reveal is if the reveal_type for that type is consistent. And Warning is if mypy generates a warning when used on 3.9 or newer.

type from Working¹ Reveal Warning
tuple typing.Tuple
list typing.List ✔️ ✔️
dict typing.Dict ✔️ ✔️
set typing.Set ✔️ ✔️
frozenset typing.FrozenSet ✔️ ✔️
type typing.Type ✔️
collections.deque ✔️ ✔️
collections.defaultdict ✔️ ✔️
collections.OrderedDict ✔️ ✔️
collections.Counter ✔️ ✔️
collections.ChainMap ✔️ ✔️
collections.abc.Awaitable ✔️
collections.abc.Coroutine ✔️
collections.abc.AsyncIterable ✔️
collections.abc.AsyncIterator ✔️
collections.abc.AsyncGenerator ✔️
collections.abc.Iterable ✔️
collections.abc.Iterator ✔️
collections.abc.Generator ✔️
collections.abc.Reversible ✔️
collections.abc.Container ✔️
collections.abc.Collection ✔️
collections.abc.Callable ✔️ ✔️
collections.abc.Set typing.AbstractSet ✔️
collections.abc.MutableSet ✔️
collections.abc.Mapping ✔️
collections.abc.MutableMapping ✔️
collections.abc.Sequence ✔️
collections.abc.MutableSequence ✔️
collections.abc.ByteString ✔️
collections.abc.MappingView
collections.abc.KeysView ✔️
collections.abc.ItemsView ✔️
collections.abc.ValuesView ✔️
contextlib.AbstractContextManager typing.ContextManager ✔️
contextlib.AbstractAsyncContextManager typing.AsyncContextManager ✔️
re.Pattern typing.Pattern, typing.re.Pattern ✔️
re.Match typing.Match, typing.re.Match ✔️

¹ Using implementation on PR #9564

collections.abc.MappingView

The type collections.abc.MappingView listed on PEP 585 doesn't work. For example, this code

t31: collections.abc.MappingView[int, int]

generates this

error: "MappingView" expects no type arguments, but 2 given.

That's because in typeshed stdlib/3/typing.pyi the MappingView (https://github.com/python/typeshed/blob/0583738a412f0ddb8255a41520cf8aeca68dc12a/stdlib/3/typing.pyi#L375) is not a generic object, as opposed with the other view classes:

class MappingView(Sized):
    ...

class ItemsView(MappingView, AbstractSet[Tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]):
    ...

class KeysView(MappingView, AbstractSet[_KT_co], Generic[_KT_co]):
    ...

class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]):
    ...

I was going to fix or open an issue in the typeshed repository, but when looking at the python documentation, it isn't what I was expecting. I think it's a bug in the documentation, but you guys tell me.

In the typings module doc, it says (https://docs.python.org/3/library/typing.html#typing.MappingView):

class typing.MappingView(Sized, Iterable[T_co])

compared with

class typing.MutableMapping(Mapping[KT, VT])
class typing.ItemsView(MappingView, Generic[KT_co, VT_co])
class typing.Mapping(Sized, Collection[KT], Generic[VT_co])

I think that it only makes sense MappingView having 2 generic parameters, for key and value, just like any other mapping/dict generic. It this is the case, the documentation should be fixed, as well in the typing module:

MappingView = _alias(collections.abc.MappingView, 1)
KeysView = _alias(collections.abc.KeysView, 1)
ItemsView = _alias(collections.abc.ItemsView, 2)
ValuesView = _alias(collections.abc.ValuesView, 1)

But if this is right, what would be the meaning of the only type parameter in the MappingView? So I could try to fix this in the other places.

Tuple vs tuple

When writing some tests for tuple, it's presenting some weird behaviours. In particular, with variable-length tuple of homogeneous type:

from typing import Tuple
T: Tuple[int, ...] = (1, 2)  # OK
t: tuple[int, ...] = (1, 2)  # error: Unexpected '...'

I'm trying to investigate it on the #9564, but any help is appreciated as I'm novel to mypy internals.
UPDATE: fix done

reveal_type()

The reveal_type() function results are not consistent. There are 2 cases: tuple, type and the typing.* case.

For tuple and type, it seems they have a special treatment in the code, and so they have special representation. While for lists and dict they use builtins.list and builtins.dict, for those they always shown as Tuple and Type. Tuple is a special case anyway. But I would expect them to be shown as builtins.tuple and builtins.type like the others. Considering that the typing.Tuple and typing.Type are deprecated, this would make more sense.

As for the others, there are a lot of types that even using the non-deprecated version in 3.9, mypy shows them like typing.. I think this should be handled too. Above the is a code that I used to generate a list of all the types and returned type of them (using python 3.9 and implementation of PR #9564):

import collections
import collections.abc
import contextlib
import re


t01: tuple[int]
t02: list[int]
t03: dict[int, str]
t04: set[int]
t05: frozenset[int]
t06: type[int]
t07: collections.deque[int]
t08: collections.defaultdict[int, str]
t09: collections.OrderedDict[int, str]
t10: collections.Counter[int]
t11: collections.ChainMap[int, str]

t12: collections.abc.Awaitable[int]
t13: collections.abc.Coroutine[str, int, float]
t14: collections.abc.AsyncIterable[int]
t15: collections.abc.AsyncIterator[int]
t16: collections.abc.AsyncGenerator[int, float]
t17: collections.abc.Iterable[int]
t18: collections.abc.Iterator[int]
t19: collections.abc.Generator[int, float, str]
t20: collections.abc.Reversible[int]
t21: collections.abc.Container[int]
t22: collections.abc.Collection[int]
t23: collections.abc.Callable[[int], float]

t24: collections.abc.Set[int]
t25: collections.abc.MutableSet[int]
t26: collections.abc.Mapping[int, str]
t27: collections.abc.MutableMapping[int, str]
t28: collections.abc.Sequence[int]
t29: collections.abc.MutableSequence[int]
t30: collections.abc.ByteString

t31: collections.abc.MappingView[int, int]		# FIX
t32: collections.abc.KeysView[int]
t33: collections.abc.ItemsView[int, str]
t34: collections.abc.ValuesView[str]

t35: contextlib.AbstractContextManager[int]
t36: contextlib.AbstractAsyncContextManager[int]
t37: re.Pattern[str]
t38: re.Match[str]

Here is the list of the revealed types. The last column is for the equivalent code running in python 3.8 using typing modules instead, i.e., instead of list, it would be typing.List, and the results are almost the same.

type hint type_reveal (3.9) type_reveal (3.8)
tuple[int] Tuple[builtins.int] Tuple[builtins.int]
list[int] builtins.list[builtins.int] builtins.list[builtins.int]
dict[int, str] builtins.dict[builtins.int, builtins.str] builtins.dict[builtins.int, builtins.str]
set[int] builtins.set[builtins.int] builtins.set[builtins.int]
frozenset[int] builtins.frozenset[builtins.int]
type[int] Type[builtins.int] Type[builtins.int]
collections.deque[int] collections.deque[builtins.int] collections.deque[builtins.int]
collections.defaultdict[int, str] collections.defaultdict[builtins.int, builtins.str] collections.defaultdict[builtins.int, builtins.str]
collections.OrderedDict[int, str] collections.OrderedDict[builtins.int, builtins.str] collections.OrderedDict[builtins.int, builtins.str]
collections.Counter[int] collections.Counter[builtins.int] collections.Counter[builtins.int]
collections.ChainMap[int, str] collections.ChainMap[builtins.int, builtins.str] collections.ChainMap[builtins.int, builtins.str]
collections.abc.Awaitable[int] typing.Awaitable[builtins.int] typing.Awaitable[builtins.int]
collections.abc.Coroutine[str, int, float] typing.Coroutine[builtins.str, builtins.int, builtins.float] typing.Coroutine[builtins.str, builtins.int, builtins.float]
collections.abc.AsyncIterable[int] typing.AsyncIterable[builtins.int] typing.AsyncIterable[builtins.int]
collections.abc.AsyncIterator[int] typing.AsyncIterator[builtins.int] typing.AsyncIterator[builtins.int]
collections.abc.AsyncGenerator[int, float] typing.AsyncGenerator[builtins.int, builtins.float] typing.AsyncGenerator[builtins.int, builtins.float]
collections.abc.Iterable[int] typing.Iterable[builtins.int] typing.Iterable[builtins.int]
collections.abc.Iterator[int] typing.Iterator[builtins.int] typing.Iterator[builtins.int]
collections.abc.Generator[int, float, str] typing.Generator[builtins.int, builtins.float, builtins.str] typing.Generator[builtins.int, builtins.float, builtins.str]
collections.abc.Reversible[int] typing.Reversible[builtins.int] typing.Reversible[builtins.int]
collections.abc.Container[int] typing.Container[builtins.int] typing.Container[builtins.int]
collections.abc.Collection[int] typing.Collection[builtins.int] typing.Collection[builtins.int]
collections.abc.Callable[[int], float] def (builtins.int) -> builtins.float def (builtins.int) -> builtins.float
collections.abc.Set[int] typing.AbstractSet[builtins.int] builtins.set[builtins.int]
collections.abc.MutableSet[int] typing.MutableSet[builtins.int] typing.MutableSet[builtins.int]
collections.abc.Mapping[int, str] typing.Mapping[builtins.int, builtins.str] typing.Mapping[builtins.int, builtins.str]
collections.abc.MutableMapping[int, str] typing.MutableMapping[builtins.int, builtins.str] typing.MutableMapping[builtins.int, builtins.str]
collections.abc.Sequence[int] typing.Sequence[builtins.int] typing.Sequence[builtins.int]
collections.abc.MutableSequence[int] typing.MutableSequence[builtins.int] typing.MutableSequence[builtins.int]
collections.abc.ByteString typing.ByteString typing.ByteString
collections.abc.MappingView[int, int] `` ``
collections.abc.KeysView[int] typing.KeysView[builtins.int] typing.KeysView[builtins.int]
collections.abc.ItemsView[int, str] typing.ItemsView[builtins.int, builtins.str] typing.ItemsView[builtins.int, builtins.str]
collections.abc.ValuesView[str] typing.ValuesView[builtins.str] typing.ValuesView[builtins.str]
contextlib.AbstractContextManager[int] typing.ContextManager[builtins.int] typing.ContextManager[builtins.int]
contextlib.AbstractAsyncContextManager[int] typing.AsyncContextManager[builtins.int] typing.AsyncContextManager[builtins.int]
re.Pattern[str] typing.Match[builtins.str] typing.Pattern[builtins.str]
re.Match[str] typing.Pattern[builtins.str] typing.Match[builtins.str]

So, as it is shown in the table,the builtins and collections types are ok, but the others (like collections.abc, contextlib and re) are being revealed as the deprecated generic alias from typing module. IMHO this should be addressed in a separated PR.

There is one weird thing: when running reveal_type inside the mypy's tests, sometimes it can give different results, like Any instead of the type. For further information, check this message in my PR (#9564), as this can be just my test that is badly written.

Deprecation warnings

As PEP 585 says

Importing those from typing is deprecated. Due to PEP 563 and the intention to minimize the runtime impact of typing, this deprecation will not generate DeprecationWarnings. Instead, type checkers may warn about such deprecated usage when the target version of the checked program is signalled to be Python 3.9 or newer. It's recommended to allow for those warnings to be silenced on a project-wide basis.

The deprecated functionality will be removed from the typing module in the first Python version released 5 years after the release of Python 3.9.0.

So it should be handled this deprecation warnings for those cases, in a different PR as well. When thinking about this, I have doubt that who will implement this might have that when running on python 3.7 / 3.8 with importing __future__.annotations should raise those warnings or not.

New issues?

Would be better to open new separated issues to each subtask remaining or just keep using this one?

@gvanrossum
Copy link
Member

Thanks, @AllanDaemon, but why do you thumbs-up and heart your own comment?

@AllanDaemon
Copy link
Contributor

Thanks, @AllanDaemon, but why do you thumbs-up and heart your own comment?

I was just playing around with it when I saw it.

@hauntsaninja
Copy link
Collaborator

Re: deprecation warnings
I agree that it's best left to another PR and that it's low priority. And this is a place where we shouldn't conflate PEP 585 and PEP 563 (aka future annotations); in Python 3.8 you'd need to import from typing to e.g. cast or type alias, which is why PEP 563 wasn't good enough. I.e., we should never raise a deprecation warning for Python 3.8 and lower.

Re: MappingView
MappingView is weird. I think it's just meant to be a common base class and actually isn't generic. But maybe someone else knows better

Re: reveal_type
I think it's okay to ship this with reveal_type showing classes from typing.py. To some extent this probably boils down to typeshed and if that's the case we shouldn't work too hard to work around it.

Re: tuple
Thanks for investigating my pretty vague comment and finding and fixing issues! I'll take a look at the updated PR soon. By the way, since you're looking at reveal_type, good to be aware of this issue: #9522

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

No branches or pull requests