Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Doc/library/ssl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,13 @@ SSL sockets also have the following additional methods and attributes:

.. versionadded:: 3.5

.. method:: SSLSocket.group()

Return the group used for doing key agreement on this connection. If no
connection has been established, returns ``None``.

.. versionadded:: next

.. method:: SSLSocket.compression()

Return the compression algorithm being used as a string, or ``None``
Expand Down Expand Up @@ -1647,6 +1654,25 @@ to speed up repeated connections from the same clients.

.. versionadded:: 3.6

.. method:: SSLContext.get_groups(*, include_aliases=False)

Get a list of groups implemented for key agreement, taking into
account the current TLS :attr:`~SSLContext.minimum_version` and
:attr:`~SSLContext.maximum_version` values. For example::

>>> ctx = ssl.create_default_context()
>>> ctx.minimum_version = ssl.TLSVersion.TLSv1_3
>>> ctx.maximum_version = ssl.TLSVersion.TLSv1_3
>>> ctx.get_groups() # doctest: +SKIP
['secp256r1', 'secp384r1', 'secp521r1', 'x25519', 'x448', ...]

By default, this method returns only the preferred IANA names for the
available groups. However, if the ``include_aliases`` parameter is set to
:const:`True` this method will also return any associated aliases such as
the ECDH curve names supported in older versions of OpenSSL.

.. versionadded:: next

.. method:: SSLContext.set_default_verify_paths()

Load a set of default "certification authority" (CA) certificates from
Expand All @@ -1672,6 +1698,19 @@ to speed up repeated connections from the same clients.
TLS 1.3 cipher suites cannot be disabled with
:meth:`~SSLContext.set_ciphers`.

.. method:: SSLContext.set_groups(groups)

Set the groups allowed for key agreement for sockets created with this
context. It should be a string in the `OpenSSL group list format
<https://docs.openssl.org/master/man3/SSL_CTX_set1_groups_list/>`_.

.. note::

When connected, the :meth:`SSLSocket.group` method of SSL sockets will
return the group used for key agreement on that connection.

.. versionadded:: next

.. method:: SSLContext.set_alpn_protocols(protocols)

Specify which protocols the socket should advertise during the SSL/TLS
Expand Down
116 changes: 116 additions & 0 deletions Doc/reference/compound_stmts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,9 @@ is equivalent to ::
class Foo(object):
pass

There may be one or more base classes; see :ref:`multiple-inheritance` below for more
information.

The class's suite is then executed in a new execution frame (see :ref:`naming`),
using a newly created local namespace and the original global namespace.
(Usually, the suite contains mostly function definitions.) When the class's
Expand Down Expand Up @@ -1490,6 +1493,119 @@ can be used to create instance variables with different implementation details.
were introduced in :pep:`318`.


.. _multiple-inheritance:

Multiple inheritance
--------------------

Python classes may have multiple base classes, a technique known as
*multiple inheritance*. The base classes are specified in the class definition
by listing them in parentheses after the class name, separated by commas.
For example, the following class definition:

.. doctest::

>>> class A: pass
>>> class B: pass
>>> class C(A, B): pass

defines a class ``C`` that inherits from classes ``A`` and ``B``.

The :term:`method resolution order` (MRO) is the order in which base classes are
searched when looking up an attribute on a class. See :ref:`python_2.3_mro` for a
description of how Python determines the MRO for a class.

Multiple inheritance is not always allowed. Attempting to define a class with multiple
inheritance will raise an error if one of the bases does not allow subclassing, if a consistent MRO
cannot be created, if no valid metaclass can be determined, or if there is an instance
layout conflict. We'll discuss each of these in turn.

First, all base classes must allow subclassing. While most classes allow subclassing,
some built-in classes do not, such as :class:`bool`:

.. doctest::

>>> class SubBool(bool): # TypeError
... pass
Traceback (most recent call last):
...
TypeError: type 'bool' is not an acceptable base type

In the resolved MRO of a class, the class's bases appear in the order they were
specified in the class's bases list. Additionally, the MRO always lists a child
class before any of its bases. A class definition will fail if it is impossible to
resolve a consistent MRO that satisfies these rules from the list of bases provided:

.. doctest::

>>> class Base: pass
>>> class Child(Base): pass
>>> class Grandchild(Base, Child): pass # TypeError
Traceback (most recent call last):
...
TypeError: Cannot create a consistent method resolution order (MRO) for bases Base, Child

In the MRO of ``Grandchild``, ``Base`` must appear before ``Child`` because it is first
in the base class list, but it must also appear after ``Child`` because it is a parent of
``Child``. This is a contradiction, so the class cannot be defined.

If some of the bases have a custom :term:`metaclass`, the metaclass of the resulting class
is chosen among the metaclasses of the bases and the explicitly specified metaclass of the
child class. It must be a metaclass that is a subclass of
all other candidate metaclasses. If no such metaclass exists among the candidates,
the class cannot be created, as explained in :ref:`metaclass-determination`.

Finally, the instance layouts of the bases must be compatible. This means that it must be
possible to compute a *solid base* for the class. Exactly which classes are solid bases
depends on the Python implementation.

.. impl-detail::

In CPython, a class is a solid base if it has a
nonempty :attr:`~object.__slots__` definition.
Many but not all classes defined in C are also solid bases, including most
builtins (such as :class:`int` or :class:`BaseException`)
but excluding most concrete :class:`Exception` classes. Generally, a C class
is a solid base if its underlying struct is different in size from its base class.

Every class has a solid base. :class:`object`, the base class, has itself as its solid base.
If there is a single base, the child class's solid base is that class if it is a solid base,
or else the base class's solid base. If there are multiple bases, we first find the solid base
for each base class to produce a list of candidate solid bases. If there is a unique solid base
that is a subclass of all others, then that class is the solid base. Otherwise, class creation
fails.

Example:

.. doctest::

>>> class Solid1:
... __slots__ = ("solid1",)
>>>
>>> class Solid2:
... __slots__ = ("solid2",)
>>>
>>> class SolidChild(Solid1):
... __slots__ = ("solid_child",)
>>>
>>> class C1: # solid base is `object`
... pass
>>>
>>> # OK: solid bases are `Solid1` and `object`, and `Solid1` is a subclass of `object`.
>>> class C2(Solid1, C1): # solid base is `Solid1`
... pass
>>>
>>> # OK: solid bases are `SolidChild` and `Solid1`, and `SolidChild` is a subclass of `Solid1`.
>>> class C3(SolidChild, Solid1): # solid base is `SolidChild`
... pass
>>>
>>> # Error: solid bases are `Solid1` and `Solid2`, but neither is a subclass of the other.
>>> class C4(Solid1, Solid2): # error: no single solid base
... pass
Traceback (most recent call last):
...
TypeError: multiple bases have instance lay-out conflict

.. _async:

Coroutines
Expand Down
4 changes: 3 additions & 1 deletion Doc/reference/datamodel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2629,7 +2629,7 @@ Notes on using *__slots__*:
* :attr:`~object.__class__` assignment works only if both classes have the
same *__slots__*.

* :ref:`Multiple inheritance <tut-multiple>` with multiple slotted parent
* :ref:`Multiple inheritance <multiple-inheritance>` with multiple slotted parent
classes can be used,
but only one parent is allowed to have attributes created by slots
(the other bases must have empty slot layouts) - violations raise
Expand Down Expand Up @@ -2779,6 +2779,8 @@ Resolving MRO entries
Core support for typing module and generic types.


.. _metaclass-determination:

Determining the appropriate metaclass
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. index::
Expand Down
3 changes: 3 additions & 0 deletions Doc/tutorial/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,9 @@ Taken together, these properties make it possible to design reliable and
extensible classes with multiple inheritance. For more detail, see
:ref:`python_2.3_mro`.

In some cases multiple inheritance is not allowed; see :ref:`multiple-inheritance`
for details.


.. _tut-private:

Expand Down
18 changes: 18 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,24 @@ ssl
supports "External PSKs" in TLSv1.3, as described in RFC 9258.
(Contributed by Will Childs-Klein in :gh:`133624`.)

* Added new methods for managing groups used for SSL key agreement

* :meth:`ssl.SSLContext.set_groups` sets the groups allowed for doing
key agreement, extending the previous
:meth:`ssl.SSLContext.set_ecdh_curve` method.
This new API provides the ability to list multiple groups and
supports fixed-field and post-quantum groups in addition to ECDH
curves. This method can also be used to control what key shares
are sent in the TLS handshake.
* :meth:`ssl.SSLSocket.group` returns the group selected for doing key
agreement on the current connection after the TLS handshake completes.
This call requires OpenSSL 3.2 or later.
* :meth:`ssl.SSLContext.get_groups` returns a list of all available key
agreement groups compatible with the minimum and maximum TLS versions
currently set in the context. This call requires OpenSSL 3.5 or later.

(Contributed by Ron Frederick in :gh:`136306`)


tarfile
-------
Expand Down
2 changes: 2 additions & 0 deletions Include/internal/pycore_dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ extern Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t has
extern Py_ssize_t _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
extern Py_ssize_t _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr);

extern int _PyDict_GetMethodStackRef(PyDictObject *dict, PyObject *name, _PyStackRef *method);

extern Py_ssize_t _PyDict_LookupIndex(PyDictObject *, PyObject *);
extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key);

Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_global_objects_fini_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(imag)
STRUCT_FOR_ID(importlib)
STRUCT_FOR_ID(in_fd)
STRUCT_FOR_ID(include_aliases)
STRUCT_FOR_ID(incoming)
STRUCT_FOR_ID(index)
STRUCT_FOR_ID(indexgroup)
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_runtime_init_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Include/internal/pycore_stackref.h
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,13 @@ _Py_TryXGetStackRef(PyObject **src, _PyStackRef *out)

#endif

#define PyStackRef_XSETREF(dst, src) \
do { \
_PyStackRef _tmp_dst_ref = (dst); \
(dst) = (src); \
PyStackRef_XCLOSE(_tmp_dst_ref); \
} while(0)

// Like Py_VISIT but for _PyStackRef fields
#define _Py_VISIT_STACKREF(ref) \
do { \
Expand Down
4 changes: 4 additions & 0 deletions Include/internal/pycore_unicodeobject_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions Lib/ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,10 @@ def cipher(self):
ssl_version, secret_bits)``."""
return self._sslobj.cipher()

def group(self):
"""Return the currently selected key agreement group name."""
return self._sslobj.group()

def shared_ciphers(self):
"""Return a list of ciphers shared by the client during the handshake or
None if this is not a valid server connection.
Expand Down Expand Up @@ -1210,6 +1214,14 @@ def cipher(self):
else:
return self._sslobj.cipher()

@_sslcopydoc
def group(self):
self._checkClosed()
if self._sslobj is None:
return None
else:
return self._sslobj.group()

@_sslcopydoc
def shared_ciphers(self):
self._checkClosed()
Expand Down
Loading
Loading