From d2a5d19dc2b2bec3ff743c6775bc89a697882766 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 30 Apr 2021 01:20:38 +0100 Subject: [PATCH 1/3] bpo-42800: Add audit events for f_code and tb_frame Accessing the following attributes will now fire PEP 578 style audit hooks as (object.__getattr__, obj, name): * PyTracebackObject: tb_frame * PyFrameObject: f_code * PyGenObject: gi_code, gi_frame * PyCoroObject: cr_code, cr_frame * PyAsyncGenObject: ag_code, ag_frame --- Doc/library/audit_events.rst | 2 +- Doc/library/stdtypes.rst | 180 ++++++++++++++++-- Doc/reference/datamodel.rst | 50 ++++- Misc/ACKS | 1 + .../2021-01-09-17-07-36.bpo-42800._dtZvW.rst | 1 + Objects/frameobject.c | 2 +- Objects/genobject.c | 14 +- Python/traceback.c | 2 +- 8 files changed, 220 insertions(+), 32 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2021-01-09-17-07-36.bpo-42800._dtZvW.rst diff --git a/Doc/library/audit_events.rst b/Doc/library/audit_events.rst index 367d56e4e37359..8227a7955bef81 100644 --- a/Doc/library/audit_events.rst +++ b/Doc/library/audit_events.rst @@ -7,7 +7,7 @@ Audit events table This table contains all events raised by :func:`sys.audit` or :c:func:`PySys_Audit` calls throughout the CPython runtime and the -standard library. These calls were added in 3.8.0 or later. +standard library. These calls were added in 3.8.0 or later (see :pep:`578`). See :func:`sys.addaudithook` and :c:func:`PySys_AddAuditHook` for information on handling these events. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 0667a601576165..c4e6b4d1186d04 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -478,6 +478,27 @@ class`. In addition, it provides a few more methods: .. versionadded:: 3.1 +.. method:: int.bit_count() + + Return the number of ones in the binary representation of the absolute + value of the integer. This is also known as the population count. + Example:: + + >>> n = 19 + >>> bin(n) + '0b10011' + >>> n.bit_count() + 3 + >>> (-n).bit_count() + 3 + + Equivalent to:: + + def bit_count(self): + return bin(self).count("1") + + .. versionadded:: 3.10 + .. method:: int.to_bytes(length, byteorder, *, signed=False) Return an array of bytes representing an integer. @@ -671,10 +692,9 @@ Here are the rules in detail: as ``-hash(-x)``. If the resulting hash is ``-1``, replace it with ``-2``. -- The particular values ``sys.hash_info.inf``, ``-sys.hash_info.inf`` - and ``sys.hash_info.nan`` are used as hash values for positive - infinity, negative infinity, or nans (respectively). (All hashable - nans have the same hash value.) +- The particular values ``sys.hash_info.inf`` and ``-sys.hash_info.inf`` + are used as hash values for positive + infinity or negative infinity (respectively). - For a :class:`complex` number ``z``, the hash values of the real and imaginary parts are combined by computing ``hash(z.real) + @@ -719,7 +739,7 @@ number, :class:`float`, or :class:`complex`:: """Compute the hash of a float x.""" if math.isnan(x): - return sys.hash_info.nan + return super().__hash__() elif math.isinf(x): return sys.hash_info.inf if x > 0 else -sys.hash_info.inf else: @@ -1560,13 +1580,15 @@ expression support in the :mod:`re` module). By default, the *errors* argument is not checked for best performances, but only used at the first encoding error. Enable the :ref:`Python Development - Mode `, or use a debug build to check *errors*. + Mode `, or use a :ref:`debug build ` to check + *errors*. .. versionchanged:: 3.1 Support for keyword arguments added. .. versionchanged:: 3.9 - The *errors* is now checked in development mode and in debug mode. + The *errors* is now checked in development mode and + in :ref:`debug mode `. .. method:: str.endswith(suffix[, start[, end]]) @@ -2689,7 +2711,7 @@ arbitrary binary data. By default, the *errors* argument is not checked for best performances, but only used at the first decoding error. Enable the :ref:`Python Development - Mode `, or use a debug build to check *errors*. + Mode `, or use a :ref:`debug build ` to check *errors*. .. note:: @@ -2701,7 +2723,8 @@ arbitrary binary data. Added support for keyword arguments. .. versionchanged:: 3.9 - The *errors* is now checked in development mode and in debug mode. + The *errors* is now checked in development mode and + in :ref:`debug mode `. .. method:: bytes.endswith(suffix[, start[, end]]) @@ -4191,7 +4214,7 @@ The constructors for both classes work the same: Note, the non-operator versions of :meth:`union`, :meth:`intersection`, - :meth:`difference`, and :meth:`symmetric_difference`, :meth:`issubset`, and + :meth:`difference`, :meth:`symmetric_difference`, :meth:`issubset`, and :meth:`issuperset` methods will accept any iterable as an argument. In contrast, their operator based counterparts require their arguments to be sets. This precludes error-prone constructions like ``set('abc') & 'cbs'`` @@ -4616,6 +4639,12 @@ support membership tests: .. versionchanged:: 3.8 Dictionary views are now reversible. +.. describe:: dictview.mapping + + Return a :class:`types.MappingProxyType` that wraps the original + dictionary to which the view refers. + + .. versionadded:: 3.10 Keys views are set-like since their entries are unique and hashable. If all values are hashable, so that ``(key, value)`` pairs are unique and hashable, @@ -4655,6 +4684,12 @@ An example of dictionary view usage:: >>> keys ^ {'sausage', 'juice'} {'juice', 'sausage', 'bacon', 'spam'} + >>> # get back a read-only proxy for the original dictionary + >>> values.mapping + mappingproxy({'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}) + >>> values.mapping['spam'] + 500 + .. _typecontextmanager: @@ -4731,10 +4766,20 @@ Compared to the overhead of setting up the runtime context, the overhead of a single class dictionary lookup is negligible. +Type Annotation Types --- :ref:`Generic Alias `, :ref:`Union ` +=============================================================================================== + +.. index:: + single: annotation; type annotation; type hint + +The core built-in types for :term:`type annotations ` are +:ref:`Generic Alias ` and :ref:`Union `. + + .. _types-genericalias: Generic Alias Type -================== +------------------ .. index:: object: GenericAlias @@ -4837,7 +4882,7 @@ in the ``GenericAlias`` object's :attr:`__args__ `. :: Standard Generic Collections ----------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ These standard library collections support parameterized generics. @@ -4882,7 +4927,7 @@ These standard library collections support parameterized generics. Special Attributes of Generic Alias ------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ All parameterized generics implement special read-only attributes. @@ -4916,6 +4961,11 @@ All parameterized generics implement special read-only attributes. (~T,) + .. note:: + A ``GenericAlias`` object with :class:`typing.ParamSpec` parameters may not + have correct ``__parameters__`` after substitution because + :class:`typing.ParamSpec` is intended primarily for static type checking. + .. seealso:: * :pep:`585` -- "Type Hinting Generics In Standard Collections" @@ -4925,6 +4975,107 @@ All parameterized generics implement special read-only attributes. .. versionadded:: 3.9 +.. _types-union: + +Union Type +---------- + +.. index:: + object: Union + pair: union; type + +A union object holds the value of the ``|`` (bitwise or) operation on +multiple :ref:`type objects `. These types are intended +primarily for :term:`type annotations `. The union type expression +enables cleaner type hinting syntax compared to :data:`typing.Union`. + +.. describe:: X | Y | ... + + Defines a union object which holds types *X*, *Y*, and so forth. ``X | Y`` + means either X or Y. It is equivalent to ``typing.Union[X, Y]``. + For example, the following function expects an argument of type + :class:`int` or :class:`float`:: + + def square(number: int | float) -> int | float: + return number ** 2 + +.. describe:: union_object == other + + Union objects can be tested for equality with other union objects. Details: + + * Unions of unions are flattened:: + + (int | str) | float == int | str | float + + * Redundant types are removed:: + + int | str | int == int | str + + * When comparing unions, the order is ignored:: + + int | str == str | int + + * It is compatible with :data:`typing.Union`:: + + int | str == typing.Union[int, str] + + * Optional types can be spelled as a union with ``None``:: + + str | None == typing.Optional[str] + +.. describe:: isinstance(obj, union_object) +.. describe:: issubclass(obj, union_object) + + Calls to :func:`isinstance` and :func:`issubclass` are also supported with a + union object:: + + >>> isinstance("", int | str) + True + + However, union objects containing :ref:`parameterized generics + ` cannot be used:: + + >>> isinstance(1, int | list[int]) + Traceback (most recent call last): + File "", line 1, in + TypeError: isinstance() argument 2 cannot contain a parameterized generic + +The user-exposed type for the union object can be accessed from +:data:`types.Union` and used for :func:`isinstance` checks. An object cannot be +instantiated from the type:: + + >>> import types + >>> isinstance(int | str, types.Union) + True + >>> types.Union() + Traceback (most recent call last): + File "", line 1, in + TypeError: cannot create 'types.Union' instances + +.. note:: + The :meth:`__or__` method for type objects was added to support the syntax + ``X | Y``. If a metaclass implements :meth:`__or__`, the Union may + override it:: + + >>> class M(type): + ... def __or__(self, other): + ... return "Hello" + ... + >>> class C(metaclass=M): + ... pass + ... + >>> C | int + 'Hello' + >>> int | C + int | __main__.C + +.. seealso:: + + :pep:`604` -- PEP proposing the ``X | Y`` syntax and the Union type. + +.. versionadded:: 3.10 + + .. _typesother: Other Built-in Types @@ -5044,6 +5195,9 @@ environment. Code objects are returned by the built-in :func:`compile` function and can be extracted from function objects through their :attr:`__code__` attribute. See also the :mod:`code` module. +Accessing ``__code__`` raises an :ref:`auditing event ` +``object.__getattr__`` with arguments ``obj`` and ``"__code__"``. + .. index:: builtin: exec builtin: eval diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 46ee8ec3cba6fc..3a812eb21471a0 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1005,6 +1005,9 @@ Internal types :attr:`f_lasti` gives the precise instruction (this is an index into the bytecode string of the code object). + Accessing ``f_code`` raises an :ref:`auditing event ` + ``object.__getattr__`` with arguments ``obj`` and ``"f_code"``. + .. index:: single: f_trace (frame attribute) single: f_trace_lines (frame attribute) @@ -1089,6 +1092,9 @@ Internal types :keyword:`try` statement with no matching except clause or with a finally clause. + Accessing ``tb_frame`` raises an :ref:`auditing event ` + ``object.__getattr__`` with arguments ``obj`` and ``"tb_frame"``. + .. index:: single: tb_next (traceback attribute) @@ -1132,9 +1138,8 @@ Internal types around any other object, usually a user-defined method object. When a static method object is retrieved from a class or a class instance, the object actually returned is the wrapped object, which is not subject to any further - transformation. Static method objects are not themselves callable, although the - objects they wrap usually are. Static method objects are created by the built-in - :func:`staticmethod` constructor. + transformation. Static method objects are also callable. Static method + objects are created by the built-in :func:`staticmethod` constructor. Class method objects A class method object, like a static method object, is a wrapper around another @@ -2447,13 +2452,6 @@ left undefined. :ref:`faq-augmented-assignment-tuple-error`), but this behavior is in fact part of the data model. - .. note:: - - Due to a bug in the dispatching mechanism for ``**=``, a class that - defines :meth:`__ipow__` but returns ``NotImplemented`` would fail to - fall back to ``x.__pow__(y)`` and ``y.__rpow__(x)``. This bug is fixed - in Python 3.10. - .. method:: object.__neg__(self) object.__pos__(self) @@ -2560,6 +2558,38 @@ For more information on context managers, see :ref:`typecontextmanager`. statement. +.. _class-pattern-matching: + +Customizing positional arguments in class pattern matching +---------------------------------------------------------- + +When using a class name in a pattern, positional arguments in the pattern are not +allowed by default, i.e. ``case MyClass(x, y)`` is typically invalid without special +support in ``MyClass``. To be able to use that kind of patterns, the class needs to +define a *__match_args__* attribute. + +.. data:: object.__match_args__ + + This class variable can be assigned a tuple of strings. When this class is + used in a class pattern with positional arguments, each positional argument will + be converted into a keyword argument, using the corresponding value in + *__match_args__* as the keyword. The absence of this attribute is equivalent to + setting it to ``()``. + +For example, if ``MyClass.__match_args__`` is ``("left", "center", "right")`` that means +that ``case MyClass(x, y)`` is equivalent to ``case MyClass(left=x, center=y)``. Note +that the number of arguments in the pattern must be smaller than or equal to the number +of elements in *__match_args__*; if it is larger, the pattern match attempt will raise +a :exc:`TypeError`. + +.. versionadded:: 3.10 + +.. seealso:: + + :pep:`634` - Structural Pattern Matching + The specification for the Python ``match`` statement. + + .. _special-lookup: Special method lookup diff --git a/Misc/ACKS b/Misc/ACKS index 9d0dffe57652a1..0aa2544d89ea62 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -713,6 +713,7 @@ Kevan Heydon Wouter van Heyst Kelsey Hightower Jason Hildebrand +Ryan Hileman Aaron Hill Joel Hillacre Richie Hindle diff --git a/Misc/NEWS.d/next/Security/2021-01-09-17-07-36.bpo-42800._dtZvW.rst b/Misc/NEWS.d/next/Security/2021-01-09-17-07-36.bpo-42800._dtZvW.rst new file mode 100644 index 00000000000000..d01c0c3073a503 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2021-01-09-17-07-36.bpo-42800._dtZvW.rst @@ -0,0 +1 @@ +Audit hooks are now fired for frame.f_code, traceback.tb_frame, and generator code/frame attribute access. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index b511e4c832c770..50846dec50e8ec 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -13,7 +13,7 @@ static PyMemberDef frame_memberlist[] = { {"f_back", T_OBJECT, OFF(f_back), READONLY}, - {"f_code", T_OBJECT, OFF(f_code), READONLY}, + {"f_code", T_OBJECT, OFF(f_code), READONLY|READ_RESTRICTED}, {"f_builtins", T_OBJECT, OFF(f_builtins), READONLY}, {"f_globals", T_OBJECT, OFF(f_globals), READONLY}, {"f_lasti", T_INT, OFF(f_lasti), READONLY}, diff --git a/Objects/genobject.c b/Objects/genobject.c index 72c93f613e0eda..bb962e1321424c 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -711,9 +711,9 @@ static PyGetSetDef gen_getsetlist[] = { }; static PyMemberDef gen_memberlist[] = { - {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY}, + {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY|READ_RESTRICTED}, {"gi_running", T_BOOL, offsetof(PyGenObject, gi_running), READONLY}, - {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY}, + {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY}|READ_RESTRICTED, {NULL} /* Sentinel */ }; @@ -931,9 +931,9 @@ static PyGetSetDef coro_getsetlist[] = { }; static PyMemberDef coro_memberlist[] = { - {"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY}, + {"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY|READ_RESTRICTED}, {"cr_running", T_BOOL, offsetof(PyCoroObject, cr_running), READONLY}, - {"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY}, + {"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY|READ_RESTRICTED}, {"cr_origin", T_OBJECT, offsetof(PyCoroObject, cr_origin), READONLY}, {NULL} /* Sentinel */ }; @@ -1328,10 +1328,12 @@ static PyGetSetDef async_gen_getsetlist[] = { }; static PyMemberDef async_gen_memberlist[] = { - {"ag_frame", T_OBJECT, offsetof(PyAsyncGenObject, ag_frame), READONLY}, + {"ag_frame", T_OBJECT, offsetof(PyAsyncGenObject, ag_frame), + READONLY|READ_RESTRICTED}, {"ag_running", T_BOOL, offsetof(PyAsyncGenObject, ag_running_async), READONLY}, - {"ag_code", T_OBJECT, offsetof(PyAsyncGenObject, ag_code), READONLY}, + {"ag_code", T_OBJECT, offsetof(PyAsyncGenObject, ag_code), + READONLY|READ_RESTRICTED}, {NULL} /* Sentinel */ }; diff --git a/Python/traceback.c b/Python/traceback.c index 5d3a65cc160e04..a9a9dd92e38ee9 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -147,7 +147,7 @@ static PyMethodDef tb_methods[] = { }; static PyMemberDef tb_memberlist[] = { - {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY}, + {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY|READ_RESTRICTED}, {"tb_lasti", T_INT, OFF(tb_lasti), READONLY}, {"tb_lineno", T_INT, OFF(tb_lineno), READONLY}, {NULL} /* Sentinel */ From 17bcb948f5dd5c2d5a841d9df76114f7e848a299 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 30 Apr 2021 01:30:07 +0100 Subject: [PATCH 2/3] Fix punctuation --- Objects/genobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/genobject.c b/Objects/genobject.c index bb962e1321424c..5ba4de82ea70e0 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -713,7 +713,7 @@ static PyGetSetDef gen_getsetlist[] = { static PyMemberDef gen_memberlist[] = { {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY|READ_RESTRICTED}, {"gi_running", T_BOOL, offsetof(PyGenObject, gi_running), READONLY}, - {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY}|READ_RESTRICTED, + {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY|READ_RESTRICTED}, {NULL} /* Sentinel */ }; From 88f60f29a728ba673731fcbfa19f233d83cfe4e8 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Mon, 3 May 2021 13:40:43 +0100 Subject: [PATCH 3/3] Fix poorly merged docs --- Doc/library/stdtypes.rst | 177 +++--------------------------------- Doc/reference/datamodel.rst | 44 ++------- 2 files changed, 23 insertions(+), 198 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index c4e6b4d1186d04..8a03b73b7650d4 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -478,27 +478,6 @@ class`. In addition, it provides a few more methods: .. versionadded:: 3.1 -.. method:: int.bit_count() - - Return the number of ones in the binary representation of the absolute - value of the integer. This is also known as the population count. - Example:: - - >>> n = 19 - >>> bin(n) - '0b10011' - >>> n.bit_count() - 3 - >>> (-n).bit_count() - 3 - - Equivalent to:: - - def bit_count(self): - return bin(self).count("1") - - .. versionadded:: 3.10 - .. method:: int.to_bytes(length, byteorder, *, signed=False) Return an array of bytes representing an integer. @@ -692,9 +671,10 @@ Here are the rules in detail: as ``-hash(-x)``. If the resulting hash is ``-1``, replace it with ``-2``. -- The particular values ``sys.hash_info.inf`` and ``-sys.hash_info.inf`` - are used as hash values for positive - infinity or negative infinity (respectively). +- The particular values ``sys.hash_info.inf``, ``-sys.hash_info.inf`` + and ``sys.hash_info.nan`` are used as hash values for positive + infinity, negative infinity, or nans (respectively). (All hashable + nans have the same hash value.) - For a :class:`complex` number ``z``, the hash values of the real and imaginary parts are combined by computing ``hash(z.real) + @@ -739,7 +719,7 @@ number, :class:`float`, or :class:`complex`:: """Compute the hash of a float x.""" if math.isnan(x): - return super().__hash__() + return sys.hash_info.nan elif math.isinf(x): return sys.hash_info.inf if x > 0 else -sys.hash_info.inf else: @@ -1580,15 +1560,13 @@ expression support in the :mod:`re` module). By default, the *errors* argument is not checked for best performances, but only used at the first encoding error. Enable the :ref:`Python Development - Mode `, or use a :ref:`debug build ` to check - *errors*. + Mode `, or use a debug build to check *errors*. .. versionchanged:: 3.1 Support for keyword arguments added. .. versionchanged:: 3.9 - The *errors* is now checked in development mode and - in :ref:`debug mode `. + The *errors* is now checked in development mode and in debug mode. .. method:: str.endswith(suffix[, start[, end]]) @@ -2711,7 +2689,7 @@ arbitrary binary data. By default, the *errors* argument is not checked for best performances, but only used at the first decoding error. Enable the :ref:`Python Development - Mode `, or use a :ref:`debug build ` to check *errors*. + Mode `, or use a debug build to check *errors*. .. note:: @@ -2723,8 +2701,7 @@ arbitrary binary data. Added support for keyword arguments. .. versionchanged:: 3.9 - The *errors* is now checked in development mode and - in :ref:`debug mode `. + The *errors* is now checked in development mode and in debug mode. .. method:: bytes.endswith(suffix[, start[, end]]) @@ -4214,7 +4191,7 @@ The constructors for both classes work the same: Note, the non-operator versions of :meth:`union`, :meth:`intersection`, - :meth:`difference`, :meth:`symmetric_difference`, :meth:`issubset`, and + :meth:`difference`, and :meth:`symmetric_difference`, :meth:`issubset`, and :meth:`issuperset` methods will accept any iterable as an argument. In contrast, their operator based counterparts require their arguments to be sets. This precludes error-prone constructions like ``set('abc') & 'cbs'`` @@ -4639,12 +4616,6 @@ support membership tests: .. versionchanged:: 3.8 Dictionary views are now reversible. -.. describe:: dictview.mapping - - Return a :class:`types.MappingProxyType` that wraps the original - dictionary to which the view refers. - - .. versionadded:: 3.10 Keys views are set-like since their entries are unique and hashable. If all values are hashable, so that ``(key, value)`` pairs are unique and hashable, @@ -4684,12 +4655,6 @@ An example of dictionary view usage:: >>> keys ^ {'sausage', 'juice'} {'juice', 'sausage', 'bacon', 'spam'} - >>> # get back a read-only proxy for the original dictionary - >>> values.mapping - mappingproxy({'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}) - >>> values.mapping['spam'] - 500 - .. _typecontextmanager: @@ -4766,20 +4731,10 @@ Compared to the overhead of setting up the runtime context, the overhead of a single class dictionary lookup is negligible. -Type Annotation Types --- :ref:`Generic Alias `, :ref:`Union ` -=============================================================================================== - -.. index:: - single: annotation; type annotation; type hint - -The core built-in types for :term:`type annotations ` are -:ref:`Generic Alias ` and :ref:`Union `. - - .. _types-genericalias: Generic Alias Type ------------------- +================== .. index:: object: GenericAlias @@ -4882,7 +4837,7 @@ in the ``GenericAlias`` object's :attr:`__args__ `. :: Standard Generic Collections -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +---------------------------- These standard library collections support parameterized generics. @@ -4927,7 +4882,7 @@ These standard library collections support parameterized generics. Special Attributes of Generic Alias -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +----------------------------------- All parameterized generics implement special read-only attributes. @@ -4961,11 +4916,6 @@ All parameterized generics implement special read-only attributes. (~T,) - .. note:: - A ``GenericAlias`` object with :class:`typing.ParamSpec` parameters may not - have correct ``__parameters__`` after substitution because - :class:`typing.ParamSpec` is intended primarily for static type checking. - .. seealso:: * :pep:`585` -- "Type Hinting Generics In Standard Collections" @@ -4975,107 +4925,6 @@ All parameterized generics implement special read-only attributes. .. versionadded:: 3.9 -.. _types-union: - -Union Type ----------- - -.. index:: - object: Union - pair: union; type - -A union object holds the value of the ``|`` (bitwise or) operation on -multiple :ref:`type objects `. These types are intended -primarily for :term:`type annotations `. The union type expression -enables cleaner type hinting syntax compared to :data:`typing.Union`. - -.. describe:: X | Y | ... - - Defines a union object which holds types *X*, *Y*, and so forth. ``X | Y`` - means either X or Y. It is equivalent to ``typing.Union[X, Y]``. - For example, the following function expects an argument of type - :class:`int` or :class:`float`:: - - def square(number: int | float) -> int | float: - return number ** 2 - -.. describe:: union_object == other - - Union objects can be tested for equality with other union objects. Details: - - * Unions of unions are flattened:: - - (int | str) | float == int | str | float - - * Redundant types are removed:: - - int | str | int == int | str - - * When comparing unions, the order is ignored:: - - int | str == str | int - - * It is compatible with :data:`typing.Union`:: - - int | str == typing.Union[int, str] - - * Optional types can be spelled as a union with ``None``:: - - str | None == typing.Optional[str] - -.. describe:: isinstance(obj, union_object) -.. describe:: issubclass(obj, union_object) - - Calls to :func:`isinstance` and :func:`issubclass` are also supported with a - union object:: - - >>> isinstance("", int | str) - True - - However, union objects containing :ref:`parameterized generics - ` cannot be used:: - - >>> isinstance(1, int | list[int]) - Traceback (most recent call last): - File "", line 1, in - TypeError: isinstance() argument 2 cannot contain a parameterized generic - -The user-exposed type for the union object can be accessed from -:data:`types.Union` and used for :func:`isinstance` checks. An object cannot be -instantiated from the type:: - - >>> import types - >>> isinstance(int | str, types.Union) - True - >>> types.Union() - Traceback (most recent call last): - File "", line 1, in - TypeError: cannot create 'types.Union' instances - -.. note:: - The :meth:`__or__` method for type objects was added to support the syntax - ``X | Y``. If a metaclass implements :meth:`__or__`, the Union may - override it:: - - >>> class M(type): - ... def __or__(self, other): - ... return "Hello" - ... - >>> class C(metaclass=M): - ... pass - ... - >>> C | int - 'Hello' - >>> int | C - int | __main__.C - -.. seealso:: - - :pep:`604` -- PEP proposing the ``X | Y`` syntax and the Union type. - -.. versionadded:: 3.10 - - .. _typesother: Other Built-in Types diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 3a812eb21471a0..403012307004ad 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1138,8 +1138,9 @@ Internal types around any other object, usually a user-defined method object. When a static method object is retrieved from a class or a class instance, the object actually returned is the wrapped object, which is not subject to any further - transformation. Static method objects are also callable. Static method - objects are created by the built-in :func:`staticmethod` constructor. + transformation. Static method objects are not themselves callable, although the + objects they wrap usually are. Static method objects are created by the built-in + :func:`staticmethod` constructor. Class method objects A class method object, like a static method object, is a wrapper around another @@ -2452,6 +2453,13 @@ left undefined. :ref:`faq-augmented-assignment-tuple-error`), but this behavior is in fact part of the data model. + .. note:: + + Due to a bug in the dispatching mechanism for ``**=``, a class that + defines :meth:`__ipow__` but returns ``NotImplemented`` would fail to + fall back to ``x.__pow__(y)`` and ``y.__rpow__(x)``. This bug is fixed + in Python 3.10. + .. method:: object.__neg__(self) object.__pos__(self) @@ -2558,38 +2566,6 @@ For more information on context managers, see :ref:`typecontextmanager`. statement. -.. _class-pattern-matching: - -Customizing positional arguments in class pattern matching ----------------------------------------------------------- - -When using a class name in a pattern, positional arguments in the pattern are not -allowed by default, i.e. ``case MyClass(x, y)`` is typically invalid without special -support in ``MyClass``. To be able to use that kind of patterns, the class needs to -define a *__match_args__* attribute. - -.. data:: object.__match_args__ - - This class variable can be assigned a tuple of strings. When this class is - used in a class pattern with positional arguments, each positional argument will - be converted into a keyword argument, using the corresponding value in - *__match_args__* as the keyword. The absence of this attribute is equivalent to - setting it to ``()``. - -For example, if ``MyClass.__match_args__`` is ``("left", "center", "right")`` that means -that ``case MyClass(x, y)`` is equivalent to ``case MyClass(left=x, center=y)``. Note -that the number of arguments in the pattern must be smaller than or equal to the number -of elements in *__match_args__*; if it is larger, the pattern match attempt will raise -a :exc:`TypeError`. - -.. versionadded:: 3.10 - -.. seealso:: - - :pep:`634` - Structural Pattern Matching - The specification for the Python ``match`` statement. - - .. _special-lookup: Special method lookup