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
This commit is contained in:
parent
715c59738e
commit
b07a50bfdd
107
pbr/core.py
107
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))
|
||||
_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)
|
||||
|
||||
# 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)
|
||||
# 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))
|
||||
|
||||
# Re-finalize the underlying Distribution
|
||||
core.Distribution.finalize_options(dist)
|
||||
# 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)
|
||||
|
||||
# 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)
|
||||
# Re-finalize the underlying Distribution
|
||||
core.Distribution.finalize_options(dist)
|
||||
|
||||
# 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))
|
||||
# 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()
|
||||
|
|
Loading…
Reference in New Issue