I'm planning to accept the following PEPs related to the type system later
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
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?)*
PEP 484 specifies that: "A # type: ignore comment on a line by itself is
equivalent to adding an inline # type: ignore to each line until the end of
the current indented block. At top indentation level this has effect of
disabling type checking until the end of file."
As far as I know, no type checker has fully implemented this behavior, and
one has implemented a behavior that is directly incompatible with the text.
A recent PR to mypy proposed to implement more of this specification and I
became concerned that some of the behavior was unintuitive. I'm concerned
that people could accidentally leave a "# type: ignore" on a line by itself
and be surprised when that disables type checking for the rest of the file.
Here's what existing type checkers do:
- *mypy*: "# type: ignore" only ever ignores errors on the current line.
Recently merged PRs added support for ignoring all errors in the current
expression (6648 <https://github.com/python/mypy/pull/6648>) and for
ignoring the whole file if the first line is "# type: ignore" (6830
<https://github.com/python/mypy/pull/6830>) and a still-open PR adds
support in 3.8 only for ignoring errors from a top-level "# type: ignore"
to the end of the file (6841 <https://github.com/python/mypy/pull/6841>).
- *pyre*: "# type: ignore" (and two other Pyre-specific ignore comments)
can either be placed on the same line as the error being suppressed, or on
a line by itself preceding the line with the error. The latter behavior
directly contradicts the text of PEP 484. A separate comment at the top of
the file can suppress all errors from a file. (
- *pytype*: In addition to "# type: ignore", supports a pytype-specific
suppression comment that can be scoped over multiple lines. Users first
disable errors with "# pytype: disable=attribute-error" on a line by
itself, then re-enable them with "# pytype: enable=attribute-error", both
on a line by itself. (
- *PyCharm*: doesn't support "# type: ignore" (
- *pyright*: doesn't support "# type: ignore" and rejected a feature
request to add it (https://github.com/microsoft/pyright/issues/108)
mypy at least also supports the @typing.no_type_check decorator, which
suppresses type errors in a whole function and is therefore close in
functionality to the block-scoped "# type: ignore" specified by PEP 484.
As a further point of comparison, I looked into how some other code quality
tools deal with magic comments:
- *flake8*: magical comment ignores errors on current line; separate
comment ignores the whole file (
- *pylint*: magical comment ignores errors on the current line or from
the beginning of a block to the end (
- *Black*: magical comment turns off formatting, and a separate comment
turns it back on (https://github.com/python/black#the-black-code-style)
- *coverage*: magical comment excludes the current line, or the line and
all the lines in the rest of the clause (e.g., the body of an if statement)
No type checker has fully implemented the PEP 484 specification and no tool
that I know of interprets magical comments in the way PEP 484 envisions
(checking is turned off until the end of the file with no way to turn it
back on). I've seen no user requests for mypy to enable the full PEP 484
behavior, but people do ask for a way to disable type checking in the whole
I propose that we change PEP 484 to only specify that a "# type: ignore" at
the very top of the file disables type checking for the whole file. This
brings the text in closer alignment with existing type checker behavior and
removes the potentially surprising behavior of "# type: ignore" in the
middle of the file.
(I did see your post in the moderation queue and let it through -- however
the mypy team, which would be most responsible for answering your question,
has been busy fighting some fires.)
I'm trying to understand what the PEP is saying and how you're
interpreting, and I'm not getting very far. I know for a fact that
Protocols work great with dunder methods. In fact the very first example in
the PEP uses `__len__` and `__iter__`, and there are several other examples
using `__iter__`, so I also know that this isn't an accident of mypy's
implementation. And mypy knows about the special rules for dunder method
So what's left to figure out is what the bullet you quote means, and
whether it should be clarified, or whether it is literally correct (about
what the implementation does).
My guess, without delving into the implementation, is that a Protocol is
*always* about the class, and that this is entirely a red herring.
Looking at the implementation (e.g. the Python 3 implementation at
doesn't give me much clarity. The code seems to be highly optimized and not
so readable. But I do see, at line 1159, what looks like the check that the
bullet refers to. The point here is simply to make sure that a protocol
doesn't inherit from a non-protocol class. Besides `object` there are
several other exceptions that appear to me to be related to internals of
the runtime typing implementation.
If you are still not satisfied, I recommend that you try to construct a
counter-example and test it against the typing_extensions modules in Python
3.7 or 3.8.
On Tue, May 21, 2019 at 8:40 AM Eric Snow <ericsnowcurrently(a)gmail.com>
> [originally I sent this to typing-sig but I guess it got caught up in
> In PEP 554  it says:
> - Implement metaclass functionality to detect whether a class is a
> protocol or not. Add a class attribute _is_protocol = True if that is
> the case. Verify that a protocol class only has protocol base classes in
> the MRO (except for object).
> The phrase "except for object" implies that having "type" in the MRO would
> not be allowed. Was that intentional?
> Perhaps I've misunderstood semantics with typing stuff (I haven't followed
> much of the discussion), but there seems to be a disconnect with how
> special ("dunder") methods are looked up (i.e. on classes). Effectively,
> an object's *class* has to implement the relevant "protocol". So
> disallowing "type" in the MRO means not using the PEP's functionality for
> "special method" protocols (as well as metaclasses in general). Have I
> understood that right? Is that on purpose?
> Thanks for working on this, BTW. It's a nice addition. :)
>  https://www.python.org/dev/peps/pep-0544/#implementation-details
> Python-Dev mailing list
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him/his **(why is my pronoun here?)*
In PEP 554  it says:
- Implement metaclass functionality to detect whether a class is a
protocol or not. Add a class attribute _is_protocol = True if that is
the case. Verify that a protocol class only has protocol base classes in
the MRO (except for object).
The phrase "except for object" implies that having "type" in the MRO would
not be allowed. Was that intentional?
Perhaps I've misunderstood semantics with typing stuff (I haven't followed
much of the discussion), but there seems to be a disconnect with how
special ("dunder") methods are looked up (i.e. on classes). Effectively,
an object's *class* has to implement the relevant "protocol". So
disallowing "type" in the MRO means not using the PEP's functionality for
"special method" protocols (as well as metaclasses in general). Have I
understood that right? Is that on purpose?
Thanks for working on this, BTW. It's a nice addition. :)
I've submitted PEP 591 to the PEPs repository.
This PEP proposes a "final" qualifier to be added to the ``typing``
module---in the form of a ``final`` decorator and a ``Final`` type
annotation---to serve three related purposes:
* Declaring that a method should not be overridden
* Declaring that a class should not be subclassed
* Declaring that a variable or attribute should not be reassigned
Discussion on the PEP happens here in typing-sig@. Minor things can be
fixed directly as PRs.
Here is the full PEP draft:
A reference implementation exists in mypy, whose documentation is here:
https://mypy.readthedocs.io/en/stable/final_attrs.html (though the PEP
Ivan's last presentation of typing improvements at the typing summit brought up a lot of potential improvements. I unfortunately didn't write down all of them, and suspect I am not alone in this matter. Is there any chance we can share the presentation with the typing-sig mailing group?
Additionally, did anyone take notes as to what the consensus was on each improvement and who was volunteering to write the PEPs? I'm asking, because I'm partial to the idea of adding shorthands for common typing idioms, and would volunteer unless someone else wants to work on it.
I was wondering where work/discussion on the numerical stack type system
from the last typing meetup is happening. A couple of TensorFlow folks
(cc'd) are looking to implement static checking of TensorFlow code and
would like to explore whether it makes sense to align their efforts with
the proposed type system changes. Specifically, they're interested in
learning some details about how broadcasting and shape checking will be
handled. Where should I point them for more information?
I'm currently thinking on ways to improved numpy numerical stack typing
(dtype mostly), when it comes to mixing the types. For example if you add
an int32 to a float64, you'll get a float64.
There is a quick and dirty way to deal with all this: use overloading, but
I won't see it scaling at all (think pytorch / tensorflow that are using
numpy dtypes and defining a ton of new functions). Also if we want to
abstract over these dtype, for example with something like
def my_add(x : dtype0, y: dtype1) -> ???:
In this case, overloading won't help. So I was thining of maybe adding a
type operator, something like
def my_add(x: dtype0, y:dtype1) -> typing.numpy.join(dtype0, dtype1):
I'm not sure that the right approach too, but since I'm new to python
typing, I wondered if such "type" operators already existed in the wild ?