[Python-checkins] Revert "bpo-32604: PEP 554 for use in test suite (GH-19985)" (#20465)

Pablo Galindo webhook-mailer at python.org
Wed May 27 17:33:18 EDT 2020


https://github.com/python/cpython/commit/7d80b35af1ee03834ae4af83e920dee89c2bc273
commit: 7d80b35af1ee03834ae4af83e920dee89c2bc273
branch: master
author: Pablo Galindo <Pablogsal at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-05-27T23:33:13+02:00
summary:

Revert "bpo-32604: PEP 554 for use in test suite (GH-19985)" (#20465)

This reverts commit 9d17cbf33df7cfb67ca0f37f6463ba5c18676641.

files:
D Lib/test/support/interpreters.py
D Lib/test/support/interpreters.rst
D Lib/test/test_interpreters.py
D Misc/NEWS.d/next/Library/2020-05-07-22-00-12.bpo-39881.E1xsNv.rst

diff --git a/Lib/test/support/interpreters.py b/Lib/test/support/interpreters.py
deleted file mode 100644
index ef9dcafb2a386..0000000000000
--- a/Lib/test/support/interpreters.py
+++ /dev/null
@@ -1,183 +0,0 @@
-"""Subinterpreters High Level Module."""
-
-import _xxsubinterpreters as _interpreters
-
-# aliases:
-from _xxsubinterpreters import (
-    ChannelError, ChannelNotFoundError, ChannelEmptyError,
-    is_shareable,
-)
-
-
-__all__ = [
-    'Interpreter', 'get_current', 'get_main', 'create', 'list_all',
-    'SendChannel', 'RecvChannel',
-    'create_channel', 'list_all_channels', 'is_shareable',
-    'ChannelError', 'ChannelNotFoundError',
-    'ChannelEmptyError',
-    ]
-
-
-def create(*, isolated=True):
-    """
-    Initialize a new (idle) Python interpreter.
-    """
-    id = _interpreters.create(isolated=isolated)
-    return Interpreter(id, isolated=isolated)
-
-
-def list_all():
-    """
-    Get all existing interpreters.
-    """
-    return [Interpreter(id) for id in
-            _interpreters.list_all()]
-
-
-def get_current():
-    """
-    Get the currently running interpreter.
-    """
-    id = _interpreters.get_current()
-    return Interpreter(id)
-
-
-def get_main():
-    """
-    Get the main interpreter.
-    """
-    id = _interpreters.get_main()
-    return Interpreter(id)
-
-
-class Interpreter:
-    """
-    The Interpreter object represents
-    a single interpreter.
-    """
-
-    def __init__(self, id, *, isolated=None):
-        self._id = id
-        self._isolated = isolated
-
-    @property
-    def id(self):
-        return self._id
-
-    @property
-    def isolated(self):
-        if self._isolated is None:
-            self._isolated = _interpreters.is_isolated(self._id)
-        return self._isolated
-
-    def is_running(self):
-        """
-        Return whether or not the identified
-        interpreter is running.
-        """
-        return _interpreters.is_running(self._id)
-
-    def close(self):
-        """
-        Finalize and destroy the interpreter.
-
-        Attempting to destroy the current
-        interpreter results in a RuntimeError.
-        """
-        return _interpreters.destroy(self._id)
-
-    def run(self, src_str, /, *, channels=None):
-        """
-        Run the given source code in the interpreter.
-        This blocks the current Python thread until done.
-        """
-        _interpreters.run_string(self._id, src_str)
-
-
-def create_channel():
-    """
-    Create a new channel for passing data between
-    interpreters.
-    """
-
-    cid = _interpreters.channel_create()
-    return (RecvChannel(cid), SendChannel(cid))
-
-
-def list_all_channels():
-    """
-    Get all open channels.
-    """
-    return [(RecvChannel(cid), SendChannel(cid))
-            for cid in _interpreters.channel_list_all()]
-
-
-_NOT_SET = object()
-
-
-class RecvChannel:
-    """
-    The RecvChannel object represents
-    a recieving channel.
-    """
-
-    def __init__(self, id):
-        self._id = id
-
-    def recv(self, *, _delay=10 / 1000):  # 10 milliseconds
-        """
-        Get the next object from the channel,
-        and wait if none have been sent.
-        Associate the interpreter with the channel.
-        """
-        import time
-        sentinel = object()
-        obj = _interpreters.channel_recv(self._id, sentinel)
-        while obj is sentinel:
-            time.sleep(_delay)
-            obj = _interpreters.channel_recv(self._id, sentinel)
-        return obj
-
-    def recv_nowait(self, default=_NOT_SET):
-        """
-        Like recv(), but return the default
-        instead of waiting.
-
-        This function is blocked by a missing low-level
-        implementation of channel_recv_wait().
-        """
-        if default is _NOT_SET:
-            return _interpreters.channel_recv(self._id)
-        else:
-            return _interpreters.channel_recv(self._id, default)
-
-
-class SendChannel:
-    """
-    The SendChannel object represents
-    a sending channel.
-    """
-
-    def __init__(self, id):
-        self._id = id
-
-    def send(self, obj):
-        """
-        Send the object (i.e. its data) to the receiving
-        end of the channel and wait. Associate the interpreter
-        with the channel.
-        """
-        import time
-        _interpreters.channel_send(self._id, obj)
-        time.sleep(2)
-
-    def send_nowait(self, obj):
-        """
-        Like send(), but return False if not received.
-
-        This function is blocked by a missing low-level
-        implementation of channel_send_wait().
-        """
-
-        _interpreters.channel_send(self._id, obj)
-        return False
diff --git a/Lib/test/support/interpreters.rst b/Lib/test/support/interpreters.rst
deleted file mode 100644
index 37a60b1072a66..0000000000000
--- a/Lib/test/support/interpreters.rst
+++ /dev/null
@@ -1,145 +0,0 @@
-High-level implementation of Subinterpreters
-============================================
-
-**Source code:** :source:`Lib/test/support/_interpreters.py`
-
---------------
-
-This module provides high-level tools for working with sub-interpreters,
-such as creating them, running code in them, or sending data between them.
-It is a wrapper around the low-level ``__xxsubinterpreters`` module.
-
-.. versionchanged:: added in 3.9
-
-Interpreter Objects
--------------------
-
-The ``Interpreter`` object represents a single interpreter.
-
-.. class:: Interpreter(id)
-
-    The class implementing a subinterpreter object.
-
-    .. method:: is_running()
-
-       Return ``True`` if the identified interpreter is running.
-
-    .. method:: close()
-
-       Destroy the interpreter. Attempting to destroy the current
-       interpreter results in a `RuntimeError`.
-
-    .. method:: run(self, src_str, /, *, channels=None):
-
-       Run the given source code in the interpreter. This blocks
-       the current thread until done. ``channels`` should be in
-       the form : `(RecvChannel, SendChannel)`.
-
-RecvChannel Objects
--------------------
-
-The ``RecvChannel`` object represents a recieving channel.
-
-.. class:: RecvChannel(id)
-
-    This class represents the receiving end of a channel.
-
-    .. method:: recv()
-
-        Get the next object from the channel, and wait if
-        none have been sent. Associate the interpreter
-        with the channel.
-
-    .. method:: recv_nowait(default=None)
-
-        Like ``recv()``, but return the default result
-        instead of waiting.
-
-
-SendChannel Objects
---------------------
-
-The ``SendChannel`` object represents a sending channel.
-
-.. class:: SendChannel(id)
-
-    This class represents the sending end of a channel.
-
-    .. method:: send(obj)
-
-       Send the object ``obj`` to the receiving end of the channel
-       and wait. Associate the interpreter with the channel.
-
-    .. method:: send_nowait(obj)
-
-        Similar to ``send()``, but returns ``False`` if
-        *obj* is not immediately received instead of blocking.
-
-
-This module defines the following global functions:
-
-
-.. function:: is_shareable(obj)
-
-   Return ``True`` if the object's data can be shared between
-   interpreters.
-
-.. function:: create_channel()
-
-   Create a new channel for passing data between interpreters.
-
-.. function:: list_all_channels()
-
-   Return all open channels.
-
-.. function:: create(*, isolated=True)
-
-   Initialize a new (idle) Python interpreter. Get the currently
-   running interpreter. This method returns an ``Interpreter`` object.
-
-.. function:: get_current()
-
-   Get the currently running interpreter. This method returns
-   an ``Interpreter`` object.
-
-.. function:: get_main()
-
-   Get the main interpreter. This method returns
-   an ``Interpreter`` object.
-
-.. function:: list_all()
-
-   Get all existing interpreters. Returns a list
-   of ``Interpreter`` objects.
-
-This module also defines the following exceptions.
-
-.. exception:: RunFailedError
-
-   This exception, a subclass of :exc:`RuntimeError`, is raised when the
-   ``Interpreter.run()`` results in an uncaught exception.
-
-.. exception:: ChannelError
-
-   This exception is a subclass of :exc:`Exception`, and is the base
-   class for all channel-related exceptions.
-
-.. exception:: ChannelNotFoundError
-
-   This exception is a subclass of :exc:`ChannelError`, and is raised
-   when the identified channel is not found.
-
-.. exception:: ChannelEmptyError
-
-   This exception is a subclass of :exc:`ChannelError`, and is raised when
-   the channel is unexpectedly empty.
-
-.. exception:: ChannelNotEmptyError
-
-   This exception is a subclass of :exc:`ChannelError`, and is raised when
-   the channel is unexpectedly not empty.
-
-.. exception:: NotReceivedError
-
-   This exception is a subclass of :exc:`ChannelError`, and is raised when
-   nothing was waiting to receive a sent object.
diff --git a/Lib/test/test_interpreters.py b/Lib/test/test_interpreters.py
deleted file mode 100644
index 3451a4c8759d8..0000000000000
--- a/Lib/test/test_interpreters.py
+++ /dev/null
@@ -1,535 +0,0 @@
-import contextlib
-import os
-import threading
-from textwrap import dedent
-import unittest
-import time
-
-import _xxsubinterpreters as _interpreters
-from test.support import interpreters
-
-
-def _captured_script(script):
-    r, w = os.pipe()
-    indented = script.replace('\n', '\n                ')
-    wrapped = dedent(f"""
-        import contextlib
-        with open({w}, 'w') as spipe:
-            with contextlib.redirect_stdout(spipe):
-                {indented}
-        """)
-    return wrapped, open(r)
-
-
-def clean_up_interpreters():
-    for interp in interpreters.list_all():
-        if interp.id == 0:  # main
-            continue
-        try:
-            interp.close()
-        except RuntimeError:
-            pass  # already destroyed
-
-
-def _run_output(interp, request, shared=None):
-    script, rpipe = _captured_script(request)
-    with rpipe:
-        interp.run(script)
-        return rpipe.read()
-
-
- at contextlib.contextmanager
-def _running(interp):
-    r, w = os.pipe()
-    def run():
-        interp.run(dedent(f"""
-            # wait for "signal"
-            with open({r}) as rpipe:
-                rpipe.read()
-            """))
-
-    t = threading.Thread(target=run)
-    t.start()
-
-    yield
-
-    with open(w, 'w') as spipe:
-        spipe.write('done')
-    t.join()
-
-
-class TestBase(unittest.TestCase):
-
-    def tearDown(self):
-        clean_up_interpreters()
-
-
-class CreateTests(TestBase):
-
-    def test_in_main(self):
-        interp = interpreters.create()
-        lst = interpreters.list_all()
-        self.assertEqual(interp.id, lst[1].id)
-
-    def test_in_thread(self):
-        lock = threading.Lock()
-        id = None
-        interp = interpreters.create()
-        lst = interpreters.list_all()
-        def f():
-            nonlocal id
-            id = interp.id
-            lock.acquire()
-            lock.release()
-
-        t = threading.Thread(target=f)
-        with lock:
-            t.start()
-        t.join()
-        self.assertEqual(interp.id, lst[1].id)
-
-    def test_in_subinterpreter(self):
-        main, = interpreters.list_all()
-        interp = interpreters.create()
-        out = _run_output(interp, dedent("""
-            from test.support import interpreters
-            interp = interpreters.create()
-            print(interp)
-            """))
-        interp2 = out.strip()
-
-        self.assertEqual(len(set(interpreters.list_all())), len({main, interp, interp2}))
-
-    def test_after_destroy_all(self):
-        before = set(interpreters.list_all())
-        # Create 3 subinterpreters.
-        interp_lst = []
-        for _ in range(3):
-            interps = interpreters.create()
-            interp_lst.append(interps)
-        # Now destroy them.
-        for interp in interp_lst:
-            interp.close()
-        # Finally, create another.
-        interp = interpreters.create()
-        self.assertEqual(len(set(interpreters.list_all())), len(before | {interp}))
-
-    def test_after_destroy_some(self):
-        before = set(interpreters.list_all())
-        # Create 3 subinterpreters.
-        interp1 = interpreters.create()
-        interp2 = interpreters.create()
-        interp3 = interpreters.create()
-        # Now destroy 2 of them.
-        interp1.close()
-        interp2.close()
-        # Finally, create another.
-        interp = interpreters.create()
-        self.assertEqual(len(set(interpreters.list_all())), len(before | {interp3, interp}))
-
-
-class GetCurrentTests(TestBase):
-
-    def test_main(self):
-        main_interp_id = _interpreters.get_main()
-        cur_interp_id =  interpreters.get_current().id
-        self.assertEqual(cur_interp_id, main_interp_id)
-
-    def test_subinterpreter(self):
-        main = _interpreters.get_main()
-        interp = interpreters.create()
-        out = _run_output(interp, dedent("""
-            from test.support import interpreters
-            cur = interpreters.get_current()
-            print(cur)
-            """))
-        cur = out.strip()
-        self.assertNotEqual(cur, main)
-
-
-class ListAllTests(TestBase):
-
-    def test_initial(self):
-        interps = interpreters.list_all()
-        self.assertEqual(1, len(interps))
-
-    def test_after_creating(self):
-        main = interpreters.get_current()
-        first = interpreters.create()
-        second = interpreters.create()
-
-        ids = []
-        for interp in interpreters.list_all():
-            ids.append(interp.id)
-
-        self.assertEqual(ids, [main.id, first.id, second.id])
-
-    def test_after_destroying(self):
-        main = interpreters.get_current()
-        first = interpreters.create()
-        second = interpreters.create()
-        first.close()
-
-        ids = []
-        for interp in interpreters.list_all():
-            ids.append(interp.id)
-
-        self.assertEqual(ids, [main.id, second.id])
-
-
-class TestInterpreterId(TestBase):
-
-    def test_in_main(self):
-        main = interpreters.get_current()
-        self.assertEqual(0, main.id)
-
-    def test_with_custom_num(self):
-        interp = interpreters.Interpreter(1)
-        self.assertEqual(1, interp.id)
-
-    def test_for_readonly_property(self):
-        interp = interpreters.Interpreter(1)
-        with self.assertRaises(AttributeError):
-            interp.id = 2
-
-
-class TestInterpreterIsRunning(TestBase):
-
-    def test_main(self):
-        main = interpreters.get_current()
-        self.assertTrue(main.is_running())
-
-    def test_subinterpreter(self):
-        interp = interpreters.create()
-        self.assertFalse(interp.is_running())
-
-        with _running(interp):
-            self.assertTrue(interp.is_running())
-        self.assertFalse(interp.is_running())
-
-    def test_from_subinterpreter(self):
-        interp = interpreters.create()
-        out = _run_output(interp, dedent(f"""
-            import _xxsubinterpreters as _interpreters
-            if _interpreters.is_running({interp.id}):
-                print(True)
-            else:
-                print(False)
-            """))
-        self.assertEqual(out.strip(), 'True')
-
-    def test_already_destroyed(self):
-        interp = interpreters.create()
-        interp.close()
-        with self.assertRaises(RuntimeError):
-            interp.is_running()
-
-
-class TestInterpreterDestroy(TestBase):
-
-    def test_basic(self):
-        interp1 = interpreters.create()
-        interp2 = interpreters.create()
-        interp3 = interpreters.create()
-        self.assertEqual(4, len(interpreters.list_all()))
-        interp2.close()
-        self.assertEqual(3, len(interpreters.list_all()))
-
-    def test_all(self):
-        before = set(interpreters.list_all())
-        interps = set()
-        for _ in range(3):
-            interp = interpreters.create()
-            interps.add(interp)
-        self.assertEqual(len(set(interpreters.list_all())), len(before | interps))
-        for interp in interps:
-            interp.close()
-        self.assertEqual(len(set(interpreters.list_all())), len(before))
-
-    def test_main(self):
-        main, = interpreters.list_all()
-        with self.assertRaises(RuntimeError):
-            main.close()
-
-        def f():
-            with self.assertRaises(RuntimeError):
-                main.close()
-
-        t = threading.Thread(target=f)
-        t.start()
-        t.join()
-
-    def test_already_destroyed(self):
-        interp = interpreters.create()
-        interp.close()
-        with self.assertRaises(RuntimeError):
-            interp.close()
-
-    def test_from_current(self):
-        main, = interpreters.list_all()
-        interp = interpreters.create()
-        script = dedent(f"""
-            from test.support import interpreters
-            try:
-                main = interpreters.get_current()
-                main.close()
-            except RuntimeError:
-                pass
-            """)
-
-        interp.run(script)
-        self.assertEqual(len(set(interpreters.list_all())), len({main, interp}))
-
-    def test_from_sibling(self):
-        main, = interpreters.list_all()
-        interp1 = interpreters.create()
-        script = dedent(f"""
-            from test.support import interpreters
-            interp2 = interpreters.create()
-            interp2.close()
-            """)
-        interp1.run(script)
-
-        self.assertEqual(len(set(interpreters.list_all())), len({main, interp1}))
-
-    def test_from_other_thread(self):
-        interp = interpreters.create()
-        def f():
-            interp.close()
-
-        t = threading.Thread(target=f)
-        t.start()
-        t.join()
-
-    def test_still_running(self):
-        main, = interpreters.list_all()
-        interp = interpreters.create()
-        with _running(interp):
-            with self.assertRaises(RuntimeError):
-                interp.close()
-            self.assertTrue(interp.is_running())
-
-
-class TestInterpreterRun(TestBase):
-
-    SCRIPT = dedent("""
-        with open('{}', 'w') as out:
-            out.write('{}')
-        """)
-    FILENAME = 'spam'
-
-    def setUp(self):
-        super().setUp()
-        self.interp = interpreters.create()
-        self._fs = None
-
-    def tearDown(self):
-        if self._fs is not None:
-            self._fs.close()
-        super().tearDown()
-
-    @property
-    def fs(self):
-        if self._fs is None:
-            self._fs = FSFixture(self)
-        return self._fs
-
-    def test_success(self):
-        script, file = _captured_script('print("it worked!", end="")')
-        with file:
-            self.interp.run(script)
-            out = file.read()
-
-        self.assertEqual(out, 'it worked!')
-
-    def test_in_thread(self):
-        script, file = _captured_script('print("it worked!", end="")')
-        with file:
-            def f():
-                self.interp.run(script)
-
-            t = threading.Thread(target=f)
-            t.start()
-            t.join()
-            out = file.read()
-
-        self.assertEqual(out, 'it worked!')
-
-    @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()")
-    def test_fork(self):
-        import tempfile
-        with tempfile.NamedTemporaryFile('w+') as file:
-            file.write('')
-            file.flush()
-
-            expected = 'spam spam spam spam spam'
-            script = dedent(f"""
-                import os
-                try:
-                    os.fork()
-                except RuntimeError:
-                    with open('{file.name}', 'w') as out:
-                        out.write('{expected}')
-                """)
-            self.interp.run(script)
-
-            file.seek(0)
-            content = file.read()
-            self.assertEqual(content, expected)
-
-    def test_already_running(self):
-        with _running(self.interp):
-            with self.assertRaises(RuntimeError):
-                self.interp.run('print("spam")')
-
-    def test_bad_script(self):
-        with self.assertRaises(TypeError):
-            self.interp.run(10)
-
-    def test_bytes_for_script(self):
-        with self.assertRaises(TypeError):
-            self.interp.run(b'print("spam")')
-
-
-class TestIsShareable(TestBase):
-
-    def test_default_shareables(self):
-        shareables = [
-                # singletons
-                None,
-                # builtin objects
-                b'spam',
-                'spam',
-                10,
-                -10,
-                ]
-        for obj in shareables:
-            with self.subTest(obj):
-                self.assertTrue(
-                    interpreters.is_shareable(obj))
-
-    def test_not_shareable(self):
-        class Cheese:
-            def __init__(self, name):
-                self.name = name
-            def __str__(self):
-                return self.name
-
-        class SubBytes(bytes):
-            """A subclass of a shareable type."""
-
-        not_shareables = [
-                # singletons
-                True,
-                False,
-                NotImplemented,
-                ...,
-                # builtin types and objects
-                type,
-                object,
-                object(),
-                Exception(),
-                100.0,
-                # user-defined types and objects
-                Cheese,
-                Cheese('Wensleydale'),
-                SubBytes(b'spam'),
-                ]
-        for obj in not_shareables:
-            with self.subTest(repr(obj)):
-                self.assertFalse(
-                    interpreters.is_shareable(obj))
-
-
-class TestChannel(TestBase):
-
-    def test_create_cid(self):
-        r, s = interpreters.create_channel()
-        self.assertIsInstance(r, interpreters.RecvChannel)
-        self.assertIsInstance(s, interpreters.SendChannel)
-
-    def test_sequential_ids(self):
-        before = interpreters.list_all_channels()
-        channels1 = interpreters.create_channel()
-        channels2 = interpreters.create_channel()
-        channels3 = interpreters.create_channel()
-        after = interpreters.list_all_channels()
-
-        self.assertEqual(len(set(after) - set(before)),
-                         len({channels1, channels2, channels3}))
-
-
-class TestSendRecv(TestBase):
-
-    def test_send_recv_main(self):
-        r, s = interpreters.create_channel()
-        orig = b'spam'
-        s.send(orig)
-        obj = r.recv()
-
-        self.assertEqual(obj, orig)
-        self.assertIsNot(obj, orig)
-
-    def test_send_recv_same_interpreter(self):
-        interp = interpreters.create()
-        out = _run_output(interp, dedent("""
-            from test.support import interpreters
-            r, s = interpreters.create_channel()
-            orig = b'spam'
-            s.send(orig)
-            obj = r.recv()
-            assert obj is not orig
-            assert obj == orig
-            """))
-
-    def test_send_recv_different_threads(self):
-        r, s = interpreters.create_channel()
-
-        def f():
-            while True:
-                try:
-                    obj = r.recv()
-                    break
-                except interpreters.ChannelEmptyError:
-                    time.sleep(0.1)
-            s.send(obj)
-        t = threading.Thread(target=f)
-        t.start()
-
-        s.send(b'spam')
-        t.join()
-        obj = r.recv()
-
-        self.assertEqual(obj, b'spam')
-
-    def test_send_recv_nowait_main(self):
-        r, s = interpreters.create_channel()
-        orig = b'spam'
-        s.send(orig)
-        obj = r.recv_nowait()
-
-        self.assertEqual(obj, orig)
-        self.assertIsNot(obj, orig)
-
-    def test_send_recv_nowait_same_interpreter(self):
-        interp = interpreters.create()
-        out = _run_output(interp, dedent("""
-            from test.support import interpreters
-            r, s = interpreters.create_channel()
-            orig = b'spam'
-            s.send(orig)
-            obj = r.recv_nowait()
-            assert obj is not orig
-            assert obj == orig
-            """))
-
-        r, s = interpreters.create_channel()
-
-        def f():
-            while True:
-                try:
-                    obj = r.recv_nowait()
-                    break
-                except _interpreters.ChannelEmptyError:
-                    time.sleep(0.1)
-            s.send(obj)
diff --git a/Misc/NEWS.d/next/Library/2020-05-07-22-00-12.bpo-39881.E1xsNv.rst b/Misc/NEWS.d/next/Library/2020-05-07-22-00-12.bpo-39881.E1xsNv.rst
deleted file mode 100644
index 1129cd7649b96..0000000000000
--- a/Misc/NEWS.d/next/Library/2020-05-07-22-00-12.bpo-39881.E1xsNv.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-PEP 554 for use in the test suite.
-(Patch By Joannah Nanjekye)
\ No newline at end of file



More information about the Python-checkins mailing list