Author: Carl Friedrich Bolz-Tereick <[email protected]>
Branch: py3.7
Changeset: r97793:690fff498e45
Date: 2019-10-16 12:45 +0000
http://bitbucket.org/pypy/pypy/changeset/690fff498e45/

Log:    Merged in Yannick_Jadoul/pypy/py3.7-pep553 (pull request #671)

        PEP 533 implementation

diff --git a/pypy/module/__builtin__/app_breakpoint.py 
b/pypy/module/__builtin__/app_breakpoint.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__builtin__/app_breakpoint.py
@@ -0,0 +1,16 @@
+# NOT_RPYTHON
+"""
+Plain Python definition of the builtin breakpoint function.
+"""
+
+import sys
+
+def breakpoint(*args, **kwargs):
+    """Call sys.breakpointhook(*args, **kws).  sys.breakpointhook() must accept
+whatever arguments are passed.
+
+By default, this drops you into the pdb debugger."""
+
+    if not hasattr(sys, 'breakpointhook'):
+        raise RuntimeError('lost sys.breakpointhook')
+    return sys.breakpointhook(*args, **kwargs)
diff --git a/pypy/module/__builtin__/moduledef.py 
b/pypy/module/__builtin__/moduledef.py
--- a/pypy/module/__builtin__/moduledef.py
+++ b/pypy/module/__builtin__/moduledef.py
@@ -23,6 +23,8 @@
         'bin'           : 'app_operation.bin',
         'oct'           : 'app_operation.oct',
         'hex'           : 'app_operation.hex',
+
+        'breakpoint'    : 'app_breakpoint.breakpoint',
     }
 
     interpleveldefs = {
diff --git a/pypy/module/__builtin__/test/test_breakpoint.py 
b/pypy/module/__builtin__/test/test_breakpoint.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__builtin__/test/test_breakpoint.py
@@ -0,0 +1,158 @@
+class AppTestBreakpoint:
+    def setup_class(cls):
+        cls.w_import_mock_pdb = cls.space.appexec([], """():
+            import sys
+            from contextlib import contextmanager
+            from types import ModuleType
+
+            @contextmanager
+            def w_import_mock_pdb():
+                try:
+                    mock_pdb = ModuleType('pdb')
+                    mock_pdb.set_trace = None
+                    sys.modules['pdb'] = mock_pdb
+                    yield mock_pdb
+                finally:
+                    del sys.modules['pdb']
+
+            return w_import_mock_pdb
+        """)
+
+        cls.w_mock_function = cls.space.appexec([], """():
+            from contextlib import contextmanager
+
+            class MockedCallable:
+                def __init__(self):
+                    self.called = 0
+
+                def __call__(self, *args, **kwargs):
+                    self.called += 1
+                    self.last_call = (args, kwargs)
+
+            @contextmanager
+            def mock_function(scope, attr, delete=False):
+                old = getattr(scope, attr)
+                try:
+                    if not delete:
+                        new = MockedCallable()
+                        setattr(scope, attr, new)
+                        yield new
+                    else:
+                        delattr(scope, attr)
+                        yield
+                finally:
+                    setattr(scope, attr, old)
+
+            return mock_function
+        """)
+
+
+    def test_default(self):
+        import sys
+        assert sys.breakpointhook is sys.__breakpointhook__
+
+        import os
+        assert 'PYTHONBREAKPOINT' not in os.environ
+
+        with self.import_mock_pdb() as pdb:
+            with self.mock_function(pdb, 'set_trace') as mocked:
+                breakpoint()
+                assert mocked.called == 1
+
+
+    def test_args_kwargs(self):
+        import sys
+        with self.import_mock_pdb() as pdb:
+            with self.mock_function(pdb, 'set_trace') as mocked:
+                breakpoint(1, 2, 3, x=4, y=5)
+                assert mocked.called == 1
+                assert mocked.last_call == ((1, 2, 3), {'x': 4, 'y': 5})
+
+
+    def test_breakpointhook(self):
+        import sys
+        with self.import_mock_pdb() as pdb:
+            with self.mock_function(sys, 'breakpointhook') as mocked, \
+                self.mock_function(pdb, 'set_trace') as mocked_pdb:
+                breakpoint()
+                assert mocked.called == 1
+                assert mocked_pdb.called == 0
+
+            with self.mock_function(pdb, 'set_trace') as mocked_pdb:
+                breakpoint()
+                assert mocked_pdb.called == 1
+
+
+    def test_breakpointhook_lost(self):
+        import sys
+        with self.import_mock_pdb() as pdb:
+            with self.mock_function(sys, 'breakpointhook', delete=True):
+                with raises(RuntimeError) as excinfo:
+                    breakpoint()
+                assert str(excinfo.value) == "lost sys.breakpointhook"
+
+
+    def test_env_default(self):
+        import os
+        try:
+            os.environ['PYTHONBREAKPOINT'] = ""
+
+            import sys
+            with self.import_mock_pdb() as pdb:
+                with self.mock_function(pdb, 'set_trace') as mocked:
+                    breakpoint()
+                    assert mocked.called == 1
+        finally:
+            del os.environ['PYTHONBREAKPOINT']
+
+
+    def test_env_disable(self):
+        import os
+        try:
+            os.environ['PYTHONBREAKPOINT'] = "0"
+
+            import sys
+            with self.import_mock_pdb() as pdb:
+                with self.mock_function(pdb, 'set_trace') as mocked:
+                    breakpoint()
+                    assert mocked.called == 0
+
+                with self.mock_function(sys, 'breakpointhook') as mocked:
+                    breakpoint()
+                    assert mocked.called == 1
+        finally:
+            del os.environ['PYTHONBREAKPOINT']
+
+
+    def test_env_other(self):
+        import os
+        try:
+            os.environ['PYTHONBREAKPOINT'] = 'sys.exit'
+
+            import sys
+            with self.import_mock_pdb() as pdb:
+                with self.mock_function(sys, 'exit') as mocked, \
+                     self.mock_function(pdb, 'set_trace') as mocked_pdb:
+                    breakpoint()
+                    assert mocked.called == 1
+                    assert mocked_pdb.called == 0
+        finally:
+            del os.environ['PYTHONBREAKPOINT']
+
+
+    def test_env_nonexistent(self):
+        import os
+        import warnings
+        try:
+            os.environ['PYTHONBREAKPOINT'] = 'blah.bleh'
+
+            import sys
+            with self.import_mock_pdb() as pdb:
+                with self.mock_function(pdb, 'set_trace') as mocked_pdb, \
+                     warnings.catch_warnings(record=True) as w:
+                    breakpoint()
+                    assert mocked_pdb.called == 0
+                    assert len(w) == 1
+                    assert str(w[-1].message) == 'Ignoring unimportable 
$PYTHONBREAKPOINT: "blah.bleh"'
+        finally:
+            del os.environ['PYTHONBREAKPOINT']
diff --git a/pypy/module/sys/app.py b/pypy/module/sys/app.py
--- a/pypy/module/sys/app.py
+++ b/pypy/module/sys/app.py
@@ -68,6 +68,31 @@
     except:
         return False    # got an exception again... ignore, report the original
 
+def breakpointhook(*args, **kwargs):
+    """This hook function is called by built-in breakpoint()."""
+
+    import importlib, os, warnings
+
+    hookname = os.getenv('PYTHONBREAKPOINT')
+    if hookname is None or len(hookname) == 0:
+        hookname = 'pdb.set_trace'
+    elif hookname == '0':
+        return None
+    modname, dot, funcname = hookname.rpartition('.')
+    if dot == '':
+        modname = 'builtins'
+
+    try:
+        module = importlib.import_module(modname)
+        hook = getattr(module, funcname)
+    except:
+        warnings.warn(
+            'Ignoring unimportable $PYTHONBREAKPOINT: "{}"'.format(hookname),
+            RuntimeWarning)
+        return None
+
+    return hook(*args, **kwargs)
+
 def exit(exitcode=None):
     """Exit the interpreter by raising SystemExit(exitcode).
 If the exitcode is omitted or None, it defaults to zero (i.e., success).
diff --git a/pypy/module/sys/moduledef.py b/pypy/module/sys/moduledef.py
--- a/pypy/module/sys/moduledef.py
+++ b/pypy/module/sys/moduledef.py
@@ -109,6 +109,8 @@
     appleveldefs = {
         'excepthook'            : 'app.excepthook',
         '__excepthook__'        : 'app.excepthook',
+        'breakpointhook'        : 'app.breakpointhook',
+        '__breakpointhook__'    : 'app.breakpointhook',
         'exit'                  : 'app.exit',
         'callstats'             : 'app.callstats',
         'copyright'             : 'app.copyright_str',
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to