[Reproducible-commits] [reprotest] 01/02: Monkey-patch contextlib.ExitStack to work around CPython bug, see https://bugs.python.org/issue25782 and https://bugs.python.org/issue25786

Ceridwen ceridwen-guest at moszumanska.debian.org
Sat Jul 16 04:17:21 UTC 2016


This is an automated email from the git hooks/post-receive script.

ceridwen-guest pushed a commit to branch virtualization
in repository reprotest.

commit 06d19d22c627a905a5db3478cc157fe2a2c48914
Author: Ceridwen <ceridwenv at gmail.com>
Date:   Sat Jul 16 00:15:08 2016 -0400

    Monkey-patch contextlib.ExitStack to work around CPython bug, see https://bugs.python.org/issue25782 and https://bugs.python.org/issue25786
---
 reprotest/__init__.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/reprotest/__init__.py b/reprotest/__init__.py
index d2627a8..c172fec 100644
--- a/reprotest/__init__.py
+++ b/reprotest/__init__.py
@@ -24,6 +24,72 @@ from reprotest import _shell_ast
 adtlog.verbosity = 2
 
 
+# Monkey-patch contextlib.ExitStack
+
+# Patch from: https://bugs.python.org/file41216/Issue25786.patch
+
+# https://bugs.python.org/issue25782
+
+# https://bugs.python.org/issue25786
+
+# This code is from the standard library contextlib
+
+def monkey_patch_exit_stack():
+    def __exit__(self, *exc_details):
+        received_exc = exc_details[0] is not None
+
+        # We manipulate the exception state so it behaves as though
+        # we were actually nesting multiple with statements
+        frame_exc = sys.exc_info()[1]
+        def _fix_exception_context(new_exc, old_exc):
+            # Context may not be correct, so find the end of the chain
+            if new_exc is old_exc:
+                return
+            while 1:
+                exc_context = new_exc.__context__
+                if exc_context is old_exc:
+                    # Context is already set correctly (see issue 20317)
+                    return
+                if exc_context is None or exc_context is frame_exc:
+                    break
+                new_exc = exc_context
+            # Change the end of the chain to point to the exception
+            # we expect it to reference
+            new_exc.__context__ = old_exc
+
+        # Callbacks are invoked in LIFO order to match the behaviour of
+        # nested context managers
+        suppressed_exc = False
+        pending_raise = False
+        while self._exit_callbacks:
+            cb = self._exit_callbacks.pop()
+            try:
+                if cb(*exc_details):
+                    suppressed_exc = True
+                    pending_raise = False
+                    exc_details = (None, None, None)
+            except:
+                new_exc_details = sys.exc_info()
+                # simulate the stack of exceptions by setting the context
+                _fix_exception_context(new_exc_details[1], exc_details[1])
+                pending_raise = True
+                exc_details = new_exc_details
+        if pending_raise:
+            try:
+                # bare "raise exc_details[1]" replaces our carefully
+                # set-up context
+                fixed_ctx = exc_details[1].__context__
+                raise exc_details[1]
+            except BaseException:
+                exc_details[1].__context__ = fixed_ctx
+                raise
+        return received_exc and suppressed_exc
+
+    contextlib.ExitStack.__exit__ = __exit__
+
+monkey_patch_exit_stack()
+
+
 # chroot is the only form of OS virtualization that's available on
 # most POSIX OSes.  Linux containers (lxc) and namespaces are specific
 # to Linux.  Some versions of BSD have jails (MacOS X?).  There are a
@@ -202,6 +268,8 @@ def build(script, source_root, built_artifact, testbed, artifact_store, env):
     testbed.check_exec(['sh', '-ec', str(new_script)], xenv=[str(k) + '=' + str(v) for k, v in env.items()])
     # print(exit_code, stdout, stderr)
     testbed.execute(['ls', '-l', source_root])
+    testbed.execute(['stat', source_root])
+    testbed.execute(['stat', built_artifact])
     testbed.command('copyup', (built_artifact, artifact_store))
 
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/reprotest.git



More information about the Reproducible-commits mailing list