Skip to content

Commit

Permalink
pythongh-74690: Document changes made to runtime-checkable protocols …
Browse files Browse the repository at this point in the history
…in 3.12 (python#103348)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
  • Loading branch information
2 people authored and warsaw committed Apr 11, 2023
1 parent a82048a commit ce6c245
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 9 deletions.
27 changes: 18 additions & 9 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1598,15 +1598,6 @@ These are not used in annotations. They are building blocks for creating generic
import threading
assert isinstance(threading.Thread(name='Bob'), Named)

.. versionchanged:: 3.12
The internal implementation of :func:`isinstance` checks against
runtime-checkable protocols now uses :func:`inspect.getattr_static`
to look up attributes (previously, :func:`hasattr` was used).
As a result, some objects which used to be considered instances
of a runtime-checkable protocol may no longer be considered instances
of that protocol on Python 3.12+, and vice versa.
Most users are unlikely to be affected by this change.

.. note::

:func:`!runtime_checkable` will check only the presence of the required
Expand All @@ -1628,6 +1619,24 @@ These are not used in annotations. They are building blocks for creating generic

.. versionadded:: 3.8

.. versionchanged:: 3.12
The internal implementation of :func:`isinstance` checks against
runtime-checkable protocols now uses :func:`inspect.getattr_static`
to look up attributes (previously, :func:`hasattr` was used).
As a result, some objects which used to be considered instances
of a runtime-checkable protocol may no longer be considered instances
of that protocol on Python 3.12+, and vice versa.
Most users are unlikely to be affected by this change.

.. versionchanged:: 3.12
The members of a runtime-checkable protocol are now considered "frozen"
at runtime as soon as the class has been created. Monkey-patching
attributes onto a runtime-checkable protocol will still work, but will
have no impact on :func:`isinstance` checks comparing objects to the
protocol. See :ref:`"What's new in Python 3.12" <whatsnew-typing-py312>`
for more details.


Other special directives
""""""""""""""""""""""""

Expand Down
35 changes: 35 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,8 @@ tempfile
The :class:`tempfile.NamedTemporaryFile` function has a new optional parameter
*delete_on_close* (Contributed by Evgeny Zorin in :gh:`58451`.)

.. _whatsnew-typing-py312:

typing
------

Expand All @@ -441,6 +443,39 @@ typing
vice versa. Most users are unlikely to be affected by this change.
(Contributed by Alex Waygood in :gh:`102433`.)

* The members of a runtime-checkable protocol are now considered "frozen" at
runtime as soon as the class has been created. Monkey-patching attributes
onto a runtime-checkable protocol will still work, but will have no impact on
:func:`isinstance` checks comparing objects to the protocol. For example::

>>> from typing import Protocol, runtime_checkable
>>> @runtime_checkable
... class HasX(Protocol):
... x = 1
...
>>> class Foo: ...
...
>>> f = Foo()
>>> isinstance(f, HasX)
False
>>> f.x = 1
>>> isinstance(f, HasX)
True
>>> HasX.y = 2
>>> isinstance(f, HasX) # unchanged, even though HasX now also has a "y" attribute
True

This change was made in order to speed up ``isinstance()`` checks against
runtime-checkable protocols.

* The performance profile of :func:`isinstance` checks against
:func:`runtime-checkable protocols <typing.runtime_checkable>` has changed
significantly. Most ``isinstance()`` checks against protocols with only a few
members should be at least 2x faster than in 3.11, and some may be 20x
faster or more. However, ``isinstance()`` checks against protocols with seven
or more members may be slower than in Python 3.11. (Contributed by Alex
Waygood in :gh:`74690` and :gh:`103193`.)

sys
---

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The members of a runtime-checkable protocol are now considered "frozen" at
runtime as soon as the class has been created. See
:ref:`"What's new in Python 3.12" <whatsnew-typing-py312>` for more details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
The performance of :func:`isinstance` checks against
:func:`runtime-checkable protocols <typing.runtime_checkable>` has been
considerably improved for protocols that only have a few members. To achieve
this improvement, several internal implementation details of the
:mod:`typing` module have been refactored, including
``typing._ProtocolMeta.__instancecheck__``,
``typing._is_callable_members_only``, and ``typing._get_protocol_attrs``.
Patches by Alex Waygood.

0 comments on commit ce6c245

Please sign in to comment.