Skip to content

Commit dfec951

Browse files
EneggJelleZijlstracarljm
authored
Apply suggestions from code review
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com> Co-authored-by: Carl Meyer <carl@oddbird.net>
1 parent b179bfb commit dfec951

File tree

1 file changed

+18
-18
lines changed

1 file changed

+18
-18
lines changed

peps/pep-9999.rst

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ Discussions-To: <REQUIRED: URL of current canonical discussion thread>
66
Status: Draft
77
Type: Standards Track
88
Topic: Typing
9-
Created: ?-Nov-2024
10-
Python-Version: 3.?
9+
Created: 18-Nov-2024
10+
Python-Version: 3.14
1111

1212

1313
Abstract
@@ -20,14 +20,14 @@ This PEP proposes expanding the scope of ``ReadOnly`` to class and protocol
2020
attributes, as a single concise way to mark them read-only. Some parity changes
2121
are also made to :data:`typing.Final`.
2222

23-
Akin to :pep:`705`, it makes no Python grammar changes. Correct usage of
23+
Akin to :pep:`705`, it makes no changes to setting attributes at runtime. Correct usage of
2424
read-only attributes is intended to be enforced only by static type checkers.
2525

2626

2727
Motivation
2828
==========
2929

30-
Python type system lacks a single concise way to mark an :term:`attribute` read-only.
30+
The Python type system lacks a single concise way to mark an :term:`attribute` read-only.
3131
This feature is common in other object-oriented languages (such as `C# <https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/readonly>`_),
3232
and is useful for restricting attribute mutation at a type checker level, as well
3333
as defining a broad interface for structural subtyping.
@@ -37,7 +37,7 @@ as defining a broad interface for structural subtyping.
3737
Classes
3838
-------
3939

40-
There are 3 major ways of achieving read-only attributes, honored by type checkers:
40+
Today, there are three major ways of achieving read-only attributes, honored by type checkers:
4141

4242
* annotating the attribute with :data:`typing.Final`::
4343

@@ -54,7 +54,7 @@ There are 3 major ways of achieving read-only attributes, honored by type checke
5454

5555
- Supported by :mod:`dataclasses` (and type checkers since `typing#1669 <https://github.com/python/typing/pull/1669>`_).
5656
- Overriding ``number`` is not possible - the specification of ``Final``
57-
imposes the name cannot be overridden in subclasses.
57+
imposes that the name cannot be overridden in subclasses.
5858

5959
* read-only proxy via ``@property``::
6060

@@ -97,10 +97,10 @@ Protocols
9797
---------
9898

9999
Paraphrasing `this post <https://github.com/python/typing/discussions/1525>`_,
100-
there is no way of defining a :class:`~typing.Protocol`, such that the only
100+
there is no way of defining an attribute ``name: T`` on a :class:`~typing.Protocol`, such that the only
101101
requirements to satisfy are:
102102

103-
1. ``hasattr(obj, name)``
103+
1. ``hasattr(obj, "name")``
104104
2. ``isinstance(obj.name, T)`` [#invalid_typevar]_
105105

106106
The above are satisfiable at runtime by all of the following:
@@ -135,9 +135,9 @@ Rationale
135135

136136
These problems can be resolved by an attribute-level :external+typing:term:`type qualifier`.
137137
``ReadOnly`` has been chosen for this role, as its name conveys the intent well,
138-
and the newly proposed changes complement its semantics defined in the :pep:`705`.
138+
and the newly proposed changes complement its semantics defined in :pep:`705`.
139139

140-
A class with a read-only instance attribute can be now defined as such::
140+
A class with a read-only instance attribute can now be defined as::
141141

142142
from typing import ReadOnly
143143

@@ -146,7 +146,7 @@ A class with a read-only instance attribute can be now defined as such::
146146
def __init__(self, id: int) -> None:
147147
self.id: ReadOnly = id
148148

149-
...and a protocol described in :ref:`protocols` is now just::
149+
...and the protocol described in :ref:`protocols` is now just::
150150

151151
from typing import Protocol, ReadOnly
152152

@@ -170,10 +170,10 @@ Specification
170170

171171
The :external+py3.13:data:`typing.ReadOnly` :external+typing:term:`type qualifier`
172172
becomes a valid annotation for :term:`attributes <attribute>` of classes and protocols.
173-
It is used to indicate that an attribute should not be reassigned or ``del``\ eted.
173+
Type checkers should error on any attempt to reassign or ``del``\ ete an attribute annotated with ``ReadOnly``.
174174

175-
The deletability rule should be extended to ``Final`` as well, as it is currently
176-
not specified.
175+
Type checkers should also error on any attempt to delete an attribute annotated as ``Final``.
176+
(This is not currently specified.)
177177

178178
Akin to ``Final``, read-only attributes do not influence the mutability of
179179
the assigned object. Immutable ABCs and containers may be used in combination with
@@ -198,8 +198,8 @@ The explicit type in ``ReadOnly[<type>]`` can be omitted if the declaration has
198198
an initializing value. A type checker should apply its usual type inference
199199
rules to determine the type of ``name``.
200200

201-
If an attribute is already implied to be read-only, like in the frozen :ref:`classes`,
202-
explicit declarations should be permitted and seen as equivalent, except ``Final``
201+
If an attribute is already implied to be read-only, like in frozen :ref:`classes`,
202+
explicit declarations should be permitted and seen as equivalent, except that ``Final``
203203
additionally forbids overriding in subclasses:
204204

205205
.. code-block:: python
@@ -364,7 +364,7 @@ Borrowing from :pep:`PEP 705 <705#inheritance>`:
364364
print(self.foo, self.bar, self.baz)
365365

366366
* In a protocol attribute declaration, ``name: ReadOnly[T]`` indicates that a structural
367-
subtype must support ``.name`` access, and the returned value is compatible with ``T``::
367+
subtype must support ``.name`` access, and the returned value is assignable to ``T``::
368368

369369
class HasName(Protocol):
370370
name: ReadOnly[str]
@@ -496,7 +496,7 @@ Extending initialization
496496
Mechanisms such as :func:`dataclasses.__post_init__` or attrs' `initialization hooks <https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization>`_
497497
augment initialization by providing a set of dunder hooks which will be called
498498
once during instance creation. The current rules would disallow assignment in those
499-
hooks. Specifying any single method in the pep isn't enough, as the naming and
499+
hooks. Specifying any single method in the PEP isn't enough, as the naming and
500500
functionality differs between mechanisms (``__post_init__`` vs ``__attrs_post_init__``).
501501

502502
``ReadOnly[ClassVar[...]]`` and ``__init_subclass__``

0 commit comments

Comments
 (0)