PEP 591 discussion: final

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:
https://www.python.org/dev/peps/pep-0591/
A reference implementation exists in mypy, whose documentation is here: https://mypy.readthedocs.io/en/stable/final_attrs.html (though the PEP takes precedence)
-sully

Thanks for the write-up Sully. Two quick questions:
1. what’s the rationale for prohibiting `Final` in loops? I have a hunch this has to do with Python leaking scopes but not entirely sure. IIRC this is fine in Java.
2.
Type checkers should infer a final attribute that is initialized in a class body as being a class variable. Variables should not be annotated with both ClassVar and Final.
I’m probably missing something here but why not support something like `attribute: ClassVar[Final[int]]`? Isn’t this conflating two unrelated concepts?
________________________________ From: Michael Sullivan sully@msully.net Sent: Monday, April 15, 2019 4:55 PM To: typing-sig@python.org Subject: [Typing-sig] PEP 591 discussion: final
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:
https://www.python.org/dev/peps/pep-0591/
A reference implementation exists in mypy, whose documentation is here: https://mypy.readthedocs.io/en/stable/final_attrs.html (though the PEP takes precedence)
-sully

On Fri, 3 May 2019 at 01:36, Dominik Gabi dkgispam@gmail.com wrote:
Thanks for the write-up Sully. Two quick questions:
- what’s the rationale for prohibiting `Final` in loops? I have a hunch
this has to do with Python leaking scopes but not entirely sure. IIRC this is fine in Java.
In some sense yes. The point is that Python cycles don't create a separate scope, they just live entirely in the enclosing scope.
Type checkers should infer a final attribute that is initialized in a
class body as being a class variable. Variables should not be annotated with both ClassVar and Final.
I’m probably missing something here but why not support something like `attribute: ClassVar[Final[int]]`? Isn’t this conflating two unrelated concepts?
The point here is that according to PEP 526 ClassVar is something that can't be _set_ on instances (only on class object itself). While it still can be _accessed_ on instances. So they are not entirely orthogonal, if something is `Final` (can't be set neither on instance nor on class) there is no point in annotating it as a ClassVar.
-- Ivan

Thanks for the write-up Sully. Two quick questions:
- what’s the rationale for prohibiting `Final` in loops? I have a hunch this has to do with Python leaking scopes but not entirely sure. IIRC this is fine in Java.
In some sense yes. The point is that Python cycles don't create a separate scope, they just live entirely in the enclosing scope.
Pyre diverges from the runtime here in that we don't allow variables to escape the scope of conditionals and loops. Would appreciate it if we could adapt the PEP to allow for that behavior.
Type checkers should infer a final attribute that is initialized in a class body as being a class variable. Variables should not be annotated with both ClassVar and Final.
I’m probably missing something here but why not support something like `attribute: ClassVar[Final[int]]`? Isn’t this conflating two unrelated concepts?
The point here is that according to PEP 526 ClassVar is something that can't be _set_ on instances (only on class object itself). While it still can be _accessed_ on instances. So they are not entirely orthogonal, if something is `Final` (can't be set neither on instance nor on class) there is no point in annotating it as a ClassVar.
Haven't looked at class variables that way before. That makes sense. Thanks for the explanation.

On Tue, May 7, 2019 at 1:01 PM Dominik Gabi dkgispam@gmail.com wrote:
- what’s the rationale for prohibiting `Final` in loops? I have a
hunch this has to do with Python leaking scopes but not entirely sure. IIRC this is fine in Java.
In some sense yes. The point is that Python cycles don't create a
separate scope, they just live entirely in the enclosing scope.
Pyre diverges from the runtime here in that we don't allow variables to escape the scope of conditionals and loops. Would appreciate it if we could adapt the PEP to allow for that behavior.
That sounds like youre deviating from expected behavior of the interpreter, and if you disagree with the interpreter about this, you are welcome to also disagree with this PEP about placement of Final. IOW I don't think the PEP should endorse this deviation.

On Tue, May 7, 2019 at 10:08 AM Guido van Rossum guido@python.org wrote:
On Tue, May 7, 2019 at 1:01 PM Dominik Gabi dkgispam@gmail.com wrote:
- what’s the rationale for prohibiting `Final` in loops? I have a hunch this has to do with Python leaking scopes but not entirely sure. IIRC this is fine in Java.
In some sense yes. The point is that Python cycles don't create a separate scope, they just live entirely in the enclosing scope.
Pyre diverges from the runtime here in that we don't allow variables to escape the scope of conditionals and loops. Would appreciate it if we could adapt the PEP to allow for that behavior.
That sounds like youre deviating from expected behavior of the interpreter, and if you disagree with the interpreter about this, you are welcome to also disagree with this PEP about placement of Final. IOW I don't think the PEP should endorse this deviation.
-- --Guido van Rossum (python.org/~guido) Pronouns: he/him/his (why is my pronoun here?)
We all diverge from the expected behavior of the interpreter by constraining dynamic behavior that we deem unsafe. E.g. mypy will not support dynamic subclassing. We clearly draw the line here differently but I don't see why the PEP should not be able to accommodate both.

What words would you put in the PEP? I would not accept anything that makes mypy not in compliance. OTOH if Pyre supports Final in a for loop, it is still in compliance — only a program that uses that isn’t.
On Tue, May 7, 2019 at 13:20 Dominik Gabi dkgispam@gmail.com wrote:
On Tue, May 7, 2019 at 10:08 AM Guido van Rossum guido@python.org wrote:
On Tue, May 7, 2019 at 1:01 PM Dominik Gabi dkgispam@gmail.com wrote:
- what’s the rationale for prohibiting `Final` in loops? I have a
hunch this has to do with Python leaking scopes but not entirely sure. IIRC this is fine in Java.
In some sense yes. The point is that Python cycles don't create a
separate scope, they just live entirely in the enclosing scope.
Pyre diverges from the runtime here in that we don't allow variables to escape the scope of conditionals and loops. Would appreciate it if we could adapt the PEP to allow for that behavior.
That sounds like youre deviating from expected behavior of the
interpreter, and if you disagree with the interpreter about this, you are welcome to also disagree with this PEP about placement of Final. IOW I don't think the PEP should endorse this deviation.
-- --Guido van Rossum (python.org/~guido) Pronouns: he/him/his (why is my pronoun here?)
We all diverge from the expected behavior of the interpreter by constraining dynamic behavior that we deem unsafe. E.g. mypy will not support dynamic subclassing. We clearly draw the line here differently but I don't see why the PEP should not be able to accommodate both.

I would simply remove the loop example from the PEP. I agree with the general definition that
There must be exactly one assignment to a final name.
In Pyre this is guaranteed to hold even if you have a final in a loop. In Mypy it’s not and therefore the error from the example makes sense for your particular implementation but not for ours.
From: Guido van Rossum guido@python.org Reply-To: "guido@python.org" guido@python.org Date: Tuesday, May 7, 2019 at 10:28 AM To: Dominik Gabi dkgispam@gmail.com Cc: Ivan Levkivskyi levkivskyi@gmail.com, Michael Sullivan sully@msully.net, "typing-sig@python.org" typing-sig@python.org Subject: Re: [Typing-sig] Re: PEP 591 discussion: final
What words would you put in the PEP? I would not accept anything that makes mypy not in compliance. OTOH if Pyre supports Final in a for loop, it is still in compliance — only a program that uses that isn’t.
On Tue, May 7, 2019 at 13:20 Dominik Gabi <dkgispam@gmail.commailto:dkgispam@gmail.com> wrote: On Tue, May 7, 2019 at 10:08 AM Guido van Rossum <guido@python.orgmailto:guido@python.org> wrote:
On Tue, May 7, 2019 at 1:01 PM Dominik Gabi <dkgispam@gmail.commailto:dkgispam@gmail.com> wrote:
- what’s the rationale for prohibiting `Final` in loops? I have a hunch this has to do with Python leaking scopes but not entirely sure. IIRC this is fine in Java.
In some sense yes. The point is that Python cycles don't create a separate scope, they just live entirely in the enclosing scope.
Pyre diverges from the runtime here in that we don't allow variables to escape the scope of conditionals and loops. Would appreciate it if we could adapt the PEP to allow for that behavior.
That sounds like youre deviating from expected behavior of the interpreter, and if you disagree with the interpreter about this, you are welcome to also disagree with this PEP about placement of Final. IOW I don't think the PEP should endorse this deviation.
-- --Guido van Rossum (python.org/~guidohttp://python.org/~guido) Pronouns: he/him/his (why is my pronoun here?)
We all diverge from the expected behavior of the interpreter by constraining dynamic behavior that we deem unsafe. E.g. mypy will not support dynamic subclassing. We clearly draw the line here differently but I don't see why the PEP should not be able to accommodate both. -- --Guido (mobile)

On Tue, May 7, 2019 at 2:30 PM Dominik Gabi dkgispam@gmail.com wrote:
I would simply remove the loop example from the PEP.
OK, but words should be added that a compliant type checker need not allow Final declarations in loops (with the explanation that the Python runtime sees this as multiple assignments to a single variable).
I agree with the general definition that
There must be *exactly one* assignment to a final name.
In Pyre this is guaranteed to hold even if you have a final in a loop. In Mypy it’s not and therefore the error from the example makes sense for your particular implementation but not for ours.
Agreed.

On Tue, May 7, 2019 at 12:54 PM Guido van Rossum guido@python.org wrote:
On Tue, May 7, 2019 at 2:30 PM Dominik Gabi dkgispam@gmail.com wrote:
I would simply remove the loop example from the PEP.
OK, but words should be added that a compliant type checker need not allow Final declarations in loops (with the explanation that the Python runtime sees this as multiple assignments to a single variable).
That sounds reasonable to me.
I agree with the general definition that
There must be exactly one assignment to a final name.
In Pyre this is guaranteed to hold even if you have a final in a loop. In Mypy it’s not and therefore the error from the example makes sense for your particular implementation but not for ours.
Agreed.
-- --Guido van Rossum (python.org/~guido) Pronouns: he/him/his (why is my pronoun here?)

Please submit a PR.
On Tue, May 7, 2019 at 13:25 Dominik Gabi dkgispam@gmail.com wrote:
On Tue, May 7, 2019 at 12:54 PM Guido van Rossum guido@python.org wrote:
On Tue, May 7, 2019 at 2:30 PM Dominik Gabi dkgispam@gmail.com wrote:
I would simply remove the loop example from the PEP.
OK, but words should be added that a compliant type checker need not
allow Final declarations in loops (with the explanation that the Python runtime sees this as multiple assignments to a single variable).
That sounds reasonable to me.
I agree with the general definition that
There must be exactly one assignment to a final name.
In Pyre this is guaranteed to hold even if you have a final in a loop.
In Mypy it’s not and therefore the error from the example makes sense for your particular implementation but not for ours.
Agreed.
-- --Guido van Rossum (python.org/~guido) Pronouns: he/him/his (why is my pronoun here?)
participants (4)
-
Dominik Gabi
-
Guido van Rossum
-
Ivan Levkivskyi
-
Michael Sullivan