From b07a50bfddda1cbb10faa64dc096ca9d855c483c Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Sun, 22 Jun 2014 14:33:58 -1000 Subject: Restore Monkeypatched Distribution Instance pbr is monkeypatching the Distribution intstance in setuptools, which is OK I guess, but then it never puts it back how it left it. As a consequence, whenever pbr installs before another project in a setup.py, it breaks setuptools for everything that comes after it. This patch will restore the Distribution instance. Closes-Bug: 1324784 Change-Id: I20fbf255c634685e82f7b11987d2725de8280b9d --- pbr/core.py | 115 ++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 66 insertions(+), 49 deletions(-) diff --git a/pbr/core.py b/pbr/core.py index f622ad0..0aff652 100644 --- a/pbr/core.py +++ b/pbr/core.py @@ -49,7 +49,17 @@ from setuptools import dist from pbr import util -core.Distribution = dist._get_unpatched(core.Distribution) +_saved_core_distribution = core.Distribution + + +def _monkeypatch_distribution(): + core.Distribution = dist._get_unpatched(core.Distribution) + + +def _restore_distribution_monkeypatch(): + core.Distribution = _saved_core_distribution + + if sys.version_info[0] == 3: string_type = str integer_types = (int,) @@ -76,52 +86,59 @@ def pbr(dist, attr, value): not work well with distributions that do use a `Distribution` subclass. """ - if not value: - return - if isinstance(value, string_type): - path = os.path.abspath(value) - else: - path = os.path.abspath('setup.cfg') - if not os.path.exists(path): - raise errors.DistutilsFileError( - 'The setup.cfg file %s does not exist.' % path) - - # Converts the setup.cfg file to setup() arguments try: - attrs = util.cfg_to_args(path) - except Exception: - e = sys.exc_info()[1] - raise errors.DistutilsSetupError( - 'Error parsing %s: %s: %s' % (path, e.__class__.__name__, e)) - - # Repeat some of the Distribution initialization code with the newly - # provided attrs - if attrs: - # Skips 'options' and 'licence' support which are rarely used; may add - # back in later if demanded - for key, val in attrs.items(): - if hasattr(dist.metadata, 'set_' + key): - getattr(dist.metadata, 'set_' + key)(val) - elif hasattr(dist.metadata, key): - setattr(dist.metadata, key, val) - elif hasattr(dist, key): - setattr(dist, key, val) - else: - msg = 'Unknown distribution option: %s' % repr(key) - warnings.warn(msg) - - # Re-finalize the underlying Distribution - core.Distribution.finalize_options(dist) - - # This bit comes out of distribute/setuptools - if isinstance(dist.metadata.version, integer_types + (float,)): - # Some people apparently take "version number" too literally :) - dist.metadata.version = str(dist.metadata.version) - - # This bit of hackery is necessary so that the Distribution will ignore - # normally unsupport command options (namely pre-hooks and post-hooks). - # dist.command_options is normally a dict mapping command names to dicts of - # their options. Now it will be a defaultdict that returns IgnoreDicts for - # the each command's options so we can pass through the unsupported options - ignore = ['pre_hook.*', 'post_hook.*'] - dist.command_options = util.DefaultGetDict(lambda: util.IgnoreDict(ignore)) + _monkeypatch_distribution() + if not value: + return + if isinstance(value, string_type): + path = os.path.abspath(value) + else: + path = os.path.abspath('setup.cfg') + if not os.path.exists(path): + raise errors.DistutilsFileError( + 'The setup.cfg file %s does not exist.' % path) + + # Converts the setup.cfg file to setup() arguments + try: + attrs = util.cfg_to_args(path) + except Exception: + e = sys.exc_info()[1] + raise errors.DistutilsSetupError( + 'Error parsing %s: %s: %s' % (path, e.__class__.__name__, e)) + + # Repeat some of the Distribution initialization code with the newly + # provided attrs + if attrs: + # Skips 'options' and 'licence' support which are rarely used; may + # add back in later if demanded + for key, val in attrs.items(): + if hasattr(dist.metadata, 'set_' + key): + getattr(dist.metadata, 'set_' + key)(val) + elif hasattr(dist.metadata, key): + setattr(dist.metadata, key, val) + elif hasattr(dist, key): + setattr(dist, key, val) + else: + msg = 'Unknown distribution option: %s' % repr(key) + warnings.warn(msg) + + # Re-finalize the underlying Distribution + core.Distribution.finalize_options(dist) + + # This bit comes out of distribute/setuptools + if isinstance(dist.metadata.version, integer_types + (float,)): + # Some people apparently take "version number" too literally :) + dist.metadata.version = str(dist.metadata.version) + + # This bit of hackery is necessary so that the Distribution will ignore + # normally unsupport command options (namely pre-hooks and post-hooks). + # dist.command_options is normally a dict mapping command names to + # dicts of their options. Now it will be a defaultdict that returns + # IgnoreDicts for the each command's options so we can pass through the + # unsupported options + ignore = ['pre_hook.*', 'post_hook.*'] + dist.command_options = util.DefaultGetDict( + lambda: util.IgnoreDict(ignore) + ) + finally: + _restore_distribution_monkeypatch() -- cgit v1.2.1