From cae9d04a0ff7b7fe196c2a4ef416b5f0f01623f3 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 19 Jan 2026 10:34:58 -0500 Subject: [PATCH 1/4] Add a terminology section. --- peps/pep-0797.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/peps/pep-0797.rst b/peps/pep-0797.rst index 3bd131278ad..9ba4c434499 100644 --- a/peps/pep-0797.rst +++ b/peps/pep-0797.rst @@ -30,6 +30,17 @@ For example: interp.prepare_main(file=proxy) interp.exec("file.write('I didn't expect the Spanish Inquisition')") +Terminology +=========== + +This PEP uses the term "share", "sharing", and "shareable" to refer to objects +that are *natively* shareable between interpreters. This differs from :pep:`734`, +which uses these terms to also describe an object that supports the :mod:`pickle` +module. + +In addition to the new :class:`SharedObjectProxy` type, the list of natively +shareable objects can be found in :ref:`the documentation `. + Motivation ========== From dd7cb49924110308263269e8ed276ac7cc2bf1e7 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 19 Jan 2026 10:41:08 -0500 Subject: [PATCH 2/4] Add a section about proxying methods. --- peps/pep-0797.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/peps/pep-0797.rst b/peps/pep-0797.rst index 9ba4c434499..b956deebde3 100644 --- a/peps/pep-0797.rst +++ b/peps/pep-0797.rst @@ -119,6 +119,26 @@ accessed in subinterpreters through a proxy: interp.exec("foo()") +Method Proxying +--------------- + +Methods on a shared object proxy will switch to their owning interpreter when +accessed. In addition, any arguments passed to the method are implicitly called +with :func:`share` to ensure they are shareable (only types that are not natively +shareable are wrapped in a proxy). The same happens to the return value of +the method. + +For example, the ``__add__`` method on an object proxy is roughly equivalent +to the following code: + +.. code-block:: python + + def __add__(self, other): + with self.switch_interpreter(): + result = self.value.__add__(share(other)) + return share(result) + + Multithreaded Scaling --------------------- From bb9ccd0b4156e653c837b54327f670ddd6ed95f9 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 19 Jan 2026 10:53:21 -0500 Subject: [PATCH 3/4] Add the __share__ method. --- peps/pep-0797.rst | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/peps/pep-0797.rst b/peps/pep-0797.rst index b956deebde3..e61f0e1838e 100644 --- a/peps/pep-0797.rst +++ b/peps/pep-0797.rst @@ -38,8 +38,9 @@ that are *natively* shareable between interpreters. This differs from :pep:`734` which uses these terms to also describe an object that supports the :mod:`pickle` module. -In addition to the new :class:`SharedObjectProxy` type, the list of natively -shareable objects can be found in :ref:`the documentation `. +In addition to the new :class:`~concurrent.interpreters.SharedObjectProxy` type, +the list of natively shareable objects can be found in :ref:`the documentation +`. Motivation ========== @@ -80,21 +81,39 @@ implementing other methods to share objects between interpreters. Specification ============= -.. class:: concurrent.interpreters.SharedObjectProxy + +.. function:: concurrent.interpreters.share(obj) + + Ensure *obj* is natively shareable. + + Otherwise, f *obj* is natively shareable, this function does not create a proxy and + simply returns *obj*. Otherwise, *obj* is wrapped in an instance of + :class:`~concurrent.interpreters.SharedObjectProxy` and returned. + + If *obj* has a :meth:`~object.__share__` method, the default behavior of + this function is overridden; the object's ``__share__`` method will be + called to convert *obj* into a natively shareable version of itself, which + will be returned by this function. If the object returned by ``__share__`` + is not natively shareable, this function raises an exception. + + +.. class:: concurrent.interpreters.SharedObjectProxy(obj) A proxy type that allows access to an object across multiple interpreters. - This cannot be constructed from Python; instead, use the - :func:`~concurrent.interpreters.share` function. + Instances of this object are natively shareable between subinterpreters. + Unlike :func:`~concurrent.interpreters.share`, *obj* will always be wrapped, + even if it is natively shareable already or already a ``SharedObjectProxy`` + instance. The object's :meth:`~object.__share__` method is not invoked if + it is available. Thus, prefer using ``share`` where possible. -.. function:: concurrent.interpreters.share(obj) - Wrap *obj* in a :class:`~concurrent.interpreters.SharedObjectProxy`, - allowing it to be used in other interpreter APIs as if it were natively - shareable. +.. function:: object.__share__() - If *obj* is natively shareable, this function does not create a proxy and - simply returns *obj*. + Return a natively shareable version of the current object. This includes + shared object proxies, as they are also natively shareable. Objects composed + of shared object proxies are also allowed, such as a :class:`tuple` whose + elements are :class:`~concurrent.interpreters.SharedObjectProxy` instances. Interpreter Switching @@ -124,9 +143,9 @@ Method Proxying Methods on a shared object proxy will switch to their owning interpreter when accessed. In addition, any arguments passed to the method are implicitly called -with :func:`share` to ensure they are shareable (only types that are not natively -shareable are wrapped in a proxy). The same happens to the return value of -the method. +with :func:`~concurrent.interpreters.share` to ensure they are shareable (only +types that are not natively shareable are wrapped in a proxy). The same happens +to the return value of the method. For example, the ``__add__`` method on an object proxy is roughly equivalent to the following code: From b2a8e5f68bc622e37d4aacaac5d3a350eb91e24e Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 19 Jan 2026 10:57:48 -0500 Subject: [PATCH 4/4] Fix typo and add an example. --- peps/pep-0797.rst | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/peps/pep-0797.rst b/peps/pep-0797.rst index e61f0e1838e..2b62db3cfe3 100644 --- a/peps/pep-0797.rst +++ b/peps/pep-0797.rst @@ -86,7 +86,7 @@ Specification Ensure *obj* is natively shareable. - Otherwise, f *obj* is natively shareable, this function does not create a proxy and + If *obj* is natively shareable, this function does not create a proxy and simply returns *obj*. Otherwise, *obj* is wrapped in an instance of :class:`~concurrent.interpreters.SharedObjectProxy` and returned. @@ -96,6 +96,23 @@ Specification will be returned by this function. If the object returned by ``__share__`` is not natively shareable, this function raises an exception. + The behavior of this function is roughly equivalent to: + + .. code-block:: python + + def share(obj): + if _is_natively_shareable(obj): + return obj + + if hasattr(obj, "__share__"): + shareable = obj.__share__() + if not _is_natively_shareable(shareable): + raise TypeError(f"__share__() returned unshareable object: {shareable!r}") + + return shareable + + return SharedObjectProxy(obj) + .. class:: concurrent.interpreters.SharedObjectProxy(obj)