diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2015-01-14 21:23:57 -0500 |
---|---|---|
committer | Jason R. Coombs <jaraco@jaraco.com> | 2015-01-14 21:23:57 -0500 |
commit | 682ec4a56933e836bd76a53d80cf90dfde07c965 (patch) | |
tree | ec29929255d06b018cfa891b38d019fa5576b149 | |
parent | 90d6c10b233ba3594332a6f9d69789dce7c1ea3e (diff) | |
download | python-setuptools-bitbucket-682ec4a56933e836bd76a53d80cf90dfde07c965.tar.gz |
Extract Exception saving behavior.
-rwxr-xr-x | setuptools/sandbox.py | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 7971f42c..37d89a2a 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -92,6 +92,37 @@ def pushd(target): os.chdir(saved) +class ExceptionSaver: + """ + A Context Manager that will save an exception, serialized, and restore it + later. + """ + def __enter__(self): + return self + + def __exit__(self, type, exc, tb): + if not exc: + return + + # dump the exception + self.saved_type = pickle.dumps(type) + self.saved_exc = pickle.dumps(exc) + self.tb = tb + + # suppress the exception + return True + + def resume(self): + "restore and re-raise any exception" + + if 'saved_exc' not in vars(self): + return + + type = pickle.loads(self.saved_type) + exc = pickle.loads(self.saved_exc) + compat.reraise(type, exc, self.tb) + + @contextlib.contextmanager def save_modules(): """ @@ -101,31 +132,20 @@ def save_modules(): outside the context. """ saved = sys.modules.copy() - try: - try: - yield saved - except: - # dump any exception - class_, exc, tb = sys.exc_info() - saved_cls = pickle.dumps(class_) - saved_exc = pickle.dumps(exc) - raise - finally: - sys.modules.update(saved) - # remove any modules imported since - del_modules = ( - mod_name for mod_name in sys.modules - if mod_name not in saved - # exclude any encodings modules. See #285 - and not mod_name.startswith('encodings.') - ) - _clear_modules(del_modules) - except: - # reload and re-raise any exception, using restored modules - class_, exc, tb = sys.exc_info() - new_cls = pickle.loads(saved_cls) - new_exc = pickle.loads(saved_exc) - compat.reraise(new_cls, new_exc, tb) + with ExceptionSaver() as saved_exc: + yield saved + + sys.modules.update(saved) + # remove any modules imported since + del_modules = ( + mod_name for mod_name in sys.modules + if mod_name not in saved + # exclude any encodings modules. See #285 + and not mod_name.startswith('encodings.') + ) + _clear_modules(del_modules) + + saved_exc.resume() def _clear_modules(module_names): |