Plan to accept PEP 544, PEP 586, PEP 589, PEP 591 -- last call for discussion
![](https://secure.gravatar.com/avatar/047f2332cde3730f1ed661eebb0c5686.jpg?s=120&d=mm&r=g)
I'm planning to accept the following PEPs related to the type system later this week: PEP 544: Protocols PEP 586: Literal Types PEP 591: Final qualifier and @final decorator PEP 589: TypedDict All of these have been proposed for and discussed before. All of these have been implemented in mypy and (AFAIK) in some other type checkers (with the exception of Protocols for module objects, which is in the design stage for mypy but not controversial in any way). No substantial opposition came up during the discussions so far. Some changes were made to some of the PEPs and it seems everyone is happy with the results. I expect that these PEPs will be accepted in time to get their implementations into the stdlib typing.py module in 3.8 beta 1, which is due May 31st (i.e., in less than two weeks!). -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>
![](https://secure.gravatar.com/avatar/d5d40a40d75ba32b1bdff02b57201cd1.jpg?s=120&d=mm&r=g)
Am 20.05.19 um 16:30 schrieb Guido van Rossum:
I look forward to these PEPs becoming part of the standard Python type system. One thing is a bit unclear to me in PEP 544, though: Can explicit protocols be used to mark classes that implement some of the protocol members dynamically. For example: ------------------------ from typing import Protocol, Any class Foo(Protocol): def bar(self) -> str: ... class ExplicitFoo(Foo): pass ExplicitFoo.bar = lambda self: "some-value" # type: ignore class ImplicitFoo: pass ImplicitFoo.bar = lambda self: "some-value" # type: ignore x1: Foo = ExplicitFoo() x2: Foo = ImplicitFoo() ------------------------ The text in the section "Explicitly declaring implementation" is a bit ambiguous about it, saying "So while it's possible to subclass a protocol explicitly, it's not necessary to do so for the sake of type-checking." In the case of ExplicitFoo, explicitly deriving from the protocol seems to be necessary. The section "Subtyping relationships with other types" actually says that ExplicitFoo is not a subtype of Foo: "A concrete type X is a subtype of protocol P if and only if X implements all protocol members of P with compatible types. ..." This contradicts the "Rejected ideas" section which says "Explicit subclassing makes it possible to force a class to be considered a subtype of a protocol ..." as well as mypy's implementation of protocols, which accepts the second to last line in the example above (but of course not the last one). Whatever the intention of the PEP, I think it would be good to clarify that. (Personally I think the latter interpretation is more useful for examples like above, or protocols implemented using __getattr__.) - Sebastian
![](https://secure.gravatar.com/avatar/337fb6df3cf57f5b7f47e573f1558cfa.jpg?s=120&d=mm&r=g)
On Mon, 20 May 2019 at 18:28, Sebastian Rittau <srittau@rittau.biz> wrote:
I don't think there is a contradiction here. `ExplicitFoo` _inherits_ `bar` from Foo. The methods in protocol bodies serve as "default implementations" unless explicitly marked as abstract. Even in this case, they are inherited, and an error will be given only at instantiation point. Actual implementation in mypy does look at MRO, but this is just an implementation detail (mostly for performance). If you have a concrete proposal about improving wording here (better as a PR), then I will be happy to consider it. -- Ivan
![](https://secure.gravatar.com/avatar/f8cbaf456d5bed4fe78d758a5e8d27fc.jpg?s=120&d=mm&r=g)
Looks all fine. Just double checking that the expectations is that for Enums you need explicit enum reference, however for IntEnum literal both the int number or the enum form is accepted, not (following the rules at https://www.python.org/dev/peps/pep-0586/#id20) ? (to follow language semantic) from enum import IntEnum class Test(IntEnum): A = 1 B = 0 M = {Test.A : 'a', Test.B : 'b'} print(M[1], M[0], M[Test.A], M[Test.B]) a b a b Another thought; for a TypedDict does this mean we (type checker) can now generate the items function as a generator of literals? Is the following the expected behaviour of a type checker? class Movie(TypedDict): name: str year: int a = {'name': 'a', 'year':int} reveal_type(tuple(a.items())) Tuple[ Tuple[Literal['name'], str], Tuple[Literal['year'], int] ] reveal_type(list(a.items()) List[ Tuple[Literal['name', 'year']], Union[int, str]] On Tue, May 21, 2019 at 11:26 PM Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
![](https://secure.gravatar.com/avatar/337fb6df3cf57f5b7f47e573f1558cfa.jpg?s=120&d=mm&r=g)
For those who doesn't follow the python/peps repo, here is a short summary of updates since the original post on May 20: * PEP 544: Remove the mention of metaclasses from implementation details * PEP 544: Mention callback protocols as an important application * PEP 589: Allow using `get()` method with arbitrary strings * PEP 589: Add section about interactions with literal types and final qualifiers: allow using string constants in addition to string literals Also please note there were couple edits to PEP 544 few days before the original post in this thread: specify modules and class objects as implementations of protocols. -- Ivan
![](https://secure.gravatar.com/avatar/047f2332cde3730f1ed661eebb0c5686.jpg?s=120&d=mm&r=g)
OK, I hereby accept all four PEPs: * PEP 544: Remove the mention of metaclasses from implementation details * PEP 544: Mention callback protocols as an important application * PEP 589: Allow using `get()` method with arbitrary strings * PEP 589: Add section about interactions with literal types and final qualifiers: allow using string constants in addition to string literals I am out of time -- Ivan (or any core dev), feel free to update the PEPs themselves with the acceptance. And you're welcome to merge the implementations that I've already approved. On Fri, May 24, 2019 at 5:06 PM Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>
![](https://secure.gravatar.com/avatar/f8cbaf456d5bed4fe78d758a5e8d27fc.jpg?s=120&d=mm&r=g)
Reading the python 3.8 release schedule ( https://www.python.org/dev/peps/pep-0569/) seems feature freeze is in 5 days. Does this mean all PRs accomplishing the above need to be merged by then? Are we on route for this? On Sun, May 26, 2019, 11:51 Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
![](https://secure.gravatar.com/avatar/d5d40a40d75ba32b1bdff02b57201cd1.jpg?s=120&d=mm&r=g)
Am 20.05.19 um 16:30 schrieb Guido van Rossum:
I look forward to these PEPs becoming part of the standard Python type system. One thing is a bit unclear to me in PEP 544, though: Can explicit protocols be used to mark classes that implement some of the protocol members dynamically. For example: ------------------------ from typing import Protocol, Any class Foo(Protocol): def bar(self) -> str: ... class ExplicitFoo(Foo): pass ExplicitFoo.bar = lambda self: "some-value" # type: ignore class ImplicitFoo: pass ImplicitFoo.bar = lambda self: "some-value" # type: ignore x1: Foo = ExplicitFoo() x2: Foo = ImplicitFoo() ------------------------ The text in the section "Explicitly declaring implementation" is a bit ambiguous about it, saying "So while it's possible to subclass a protocol explicitly, it's not necessary to do so for the sake of type-checking." In the case of ExplicitFoo, explicitly deriving from the protocol seems to be necessary. The section "Subtyping relationships with other types" actually says that ExplicitFoo is not a subtype of Foo: "A concrete type X is a subtype of protocol P if and only if X implements all protocol members of P with compatible types. ..." This contradicts the "Rejected ideas" section which says "Explicit subclassing makes it possible to force a class to be considered a subtype of a protocol ..." as well as mypy's implementation of protocols, which accepts the second to last line in the example above (but of course not the last one). Whatever the intention of the PEP, I think it would be good to clarify that. (Personally I think the latter interpretation is more useful for examples like above, or protocols implemented using __getattr__.) - Sebastian
![](https://secure.gravatar.com/avatar/337fb6df3cf57f5b7f47e573f1558cfa.jpg?s=120&d=mm&r=g)
On Mon, 20 May 2019 at 18:28, Sebastian Rittau <srittau@rittau.biz> wrote:
I don't think there is a contradiction here. `ExplicitFoo` _inherits_ `bar` from Foo. The methods in protocol bodies serve as "default implementations" unless explicitly marked as abstract. Even in this case, they are inherited, and an error will be given only at instantiation point. Actual implementation in mypy does look at MRO, but this is just an implementation detail (mostly for performance). If you have a concrete proposal about improving wording here (better as a PR), then I will be happy to consider it. -- Ivan
![](https://secure.gravatar.com/avatar/f8cbaf456d5bed4fe78d758a5e8d27fc.jpg?s=120&d=mm&r=g)
Looks all fine. Just double checking that the expectations is that for Enums you need explicit enum reference, however for IntEnum literal both the int number or the enum form is accepted, not (following the rules at https://www.python.org/dev/peps/pep-0586/#id20) ? (to follow language semantic) from enum import IntEnum class Test(IntEnum): A = 1 B = 0 M = {Test.A : 'a', Test.B : 'b'} print(M[1], M[0], M[Test.A], M[Test.B]) a b a b Another thought; for a TypedDict does this mean we (type checker) can now generate the items function as a generator of literals? Is the following the expected behaviour of a type checker? class Movie(TypedDict): name: str year: int a = {'name': 'a', 'year':int} reveal_type(tuple(a.items())) Tuple[ Tuple[Literal['name'], str], Tuple[Literal['year'], int] ] reveal_type(list(a.items()) List[ Tuple[Literal['name', 'year']], Union[int, str]] On Tue, May 21, 2019 at 11:26 PM Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
![](https://secure.gravatar.com/avatar/337fb6df3cf57f5b7f47e573f1558cfa.jpg?s=120&d=mm&r=g)
For those who doesn't follow the python/peps repo, here is a short summary of updates since the original post on May 20: * PEP 544: Remove the mention of metaclasses from implementation details * PEP 544: Mention callback protocols as an important application * PEP 589: Allow using `get()` method with arbitrary strings * PEP 589: Add section about interactions with literal types and final qualifiers: allow using string constants in addition to string literals Also please note there were couple edits to PEP 544 few days before the original post in this thread: specify modules and class objects as implementations of protocols. -- Ivan
![](https://secure.gravatar.com/avatar/047f2332cde3730f1ed661eebb0c5686.jpg?s=120&d=mm&r=g)
OK, I hereby accept all four PEPs: * PEP 544: Remove the mention of metaclasses from implementation details * PEP 544: Mention callback protocols as an important application * PEP 589: Allow using `get()` method with arbitrary strings * PEP 589: Add section about interactions with literal types and final qualifiers: allow using string constants in addition to string literals I am out of time -- Ivan (or any core dev), feel free to update the PEPs themselves with the acceptance. And you're welcome to merge the implementations that I've already approved. On Fri, May 24, 2019 at 5:06 PM Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>
![](https://secure.gravatar.com/avatar/f8cbaf456d5bed4fe78d758a5e8d27fc.jpg?s=120&d=mm&r=g)
Reading the python 3.8 release schedule ( https://www.python.org/dev/peps/pep-0569/) seems feature freeze is in 5 days. Does this mean all PRs accomplishing the above need to be merged by then? Are we on route for this? On Sun, May 26, 2019, 11:51 Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
participants (4)
-
Bernat Gabor
-
Guido van Rossum
-
Ivan Levkivskyi
-
Sebastian Rittau