diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2012-11-26 09:20:11 -0500 |
---|---|---|
committer | Jason R. Coombs <jaraco@jaraco.com> | 2012-11-26 09:20:11 -0500 |
commit | ceb03af882740ae02ef4be004a30b45c7b25b9ce (patch) | |
tree | cb576f8a6f5979aedcb3ce0a5b9585059e4f3f59 | |
parent | f31fb0ff20c63dd9bb82f91af45c12e97428e38c (diff) | |
download | external_python_setuptools-ceb03af882740ae02ef4be004a30b45c7b25b9ce.tar.gz external_python_setuptools-ceb03af882740ae02ef4be004a30b45c7b25b9ce.tar.bz2 external_python_setuptools-ceb03af882740ae02ef4be004a30b45c7b25b9ce.zip |
Backed out changeset: 98a9f9dcce0e; Fixes #335.
--HG--
branch : distribute
extra : rebase_source : 3f4ff1c880688e6dd72d2fa8fab3c07e7f486a7e
-rw-r--r-- | pkg_resources.py | 60 | ||||
-rw-r--r-- | setuptools/dist.py | 5 | ||||
-rw-r--r-- | setuptools/tests/test_easy_install.py | 142 |
3 files changed, 59 insertions, 148 deletions
diff --git a/pkg_resources.py b/pkg_resources.py index a39a32dc..a5a10eb4 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -517,7 +517,7 @@ class WorkingSet(object): seen[key]=1 yield self.by_key[key] - def add(self, dist, entry=None, insert=True, replace=False): + def add(self, dist, entry=None, insert=True): """Add `dist` to working set, associated with `entry` If `entry` is unspecified, it defaults to the ``.location`` of `dist`. @@ -525,9 +525,8 @@ class WorkingSet(object): set's ``.entries`` (if it wasn't already present). `dist` is only added to the working set if it's for a project that - doesn't already have a distribution in the set, unless `replace=True`. - If it's added, any callbacks registered with the ``subscribe()`` method - will be called. + doesn't already have a distribution in the set. If it's added, any + callbacks registered with the ``subscribe()`` method will be called. """ if insert: dist.insert_on(self.entries, entry) @@ -536,7 +535,7 @@ class WorkingSet(object): entry = dist.location keys = self.entry_keys.setdefault(entry,[]) keys2 = self.entry_keys.setdefault(dist.location,[]) - if not replace and dist.key in self.by_key: + if dist.key in self.by_key: return # ignore hidden distros self.by_key[dist.key] = dist @@ -546,8 +545,7 @@ class WorkingSet(object): keys2.append(dist.key) self._added_new(dist) - def resolve(self, requirements, env=None, installer=None, - replacement=True, replace_conflicting=False): + def resolve(self, requirements, env=None, installer=None, replacement=True): """List all distributions needed to (recursively) meet `requirements` `requirements` must be a sequence of ``Requirement`` objects. `env`, @@ -557,12 +555,6 @@ class WorkingSet(object): will be invoked with each requirement that cannot be met by an already-installed distribution; it should return a ``Distribution`` or ``None``. - - Unless `replace_conflicting=True`, raises a VersionConflict exception if - any requirements are found on the path that have the correct name but - the wrong version. Otherwise, if an `installer` is supplied it will be - invoked to obtain the correct version of the requirement and activate - it. """ requirements = list(requirements)[::-1] # set up the stack @@ -582,18 +574,10 @@ class WorkingSet(object): if dist is None: # Find the best distribution and add it to the map dist = self.by_key.get(req.key) - if dist is None or (dist not in req and replace_conflicting): - ws = self + if dist is None: if env is None: - if dist is None: - env = Environment(self.entries) - else: - # Use an empty environment and workingset to avoid - # any further conflicts with the conflicting - # distribution - env = Environment([]) - ws = WorkingSet([]) - dist = best[req.key] = env.best_match(req, ws, installer) + env = Environment(self.entries) + dist = best[req.key] = env.best_match(req, self, installer) if dist is None: #msg = ("The '%s' distribution was not found on this " # "system, and is required by this application.") @@ -1814,7 +1798,6 @@ def register_namespace_handler(importer_type, namespace_handler): def _handle_ns(packageName, path_item): """Ensure that named package includes a subpath of path_item (if needed)""" - importer = get_importer(path_item) if importer is None: return None @@ -1824,19 +1807,14 @@ def _handle_ns(packageName, path_item): module = sys.modules.get(packageName) if module is None: module = sys.modules[packageName] = types.ModuleType(packageName) - module.__path__ = [] - _set_parent_ns(packageName) + module.__path__ = []; _set_parent_ns(packageName) elif not hasattr(module,'__path__'): raise TypeError("Not a package:", packageName) handler = _find_adapter(_namespace_handlers, importer) - subpath = handler(importer, path_item, packageName, module) + subpath = handler(importer,path_item,packageName,module) if subpath is not None: - path = module.__path__ - path.append(subpath) - loader.load_module(packageName) - for path_item in path: - if path_item not in module.__path__: - module.__path__.append(path_item) + path = module.__path__; path.append(subpath) + loader.load_module(packageName); module.__path__ = path return subpath def declare_namespace(packageName): @@ -2142,7 +2120,7 @@ def _remove_md5_fragment(location): class Distribution(object): """Wrap an actual or potential sys.path entry w/metadata""" PKG_INFO = 'PKG-INFO' - + def __init__(self, location=None, metadata=None, project_name=None, version=None, py_version=PY_MAJOR, platform=None, precedence = EGG_DIST @@ -2481,7 +2459,7 @@ class DistInfoDistribution(Distribution): from email.parser import Parser self._pkg_info = Parser().parsestr(self.get_metadata(self.PKG_INFO)) return self._pkg_info - + @property def _dep_map(self): try: @@ -2492,7 +2470,7 @@ class DistInfoDistribution(Distribution): def _preparse_requirement(self, requires_dist): """Convert 'Foobar (1); baz' to ('Foobar ==1', 'baz') - Split environment marker, add == prefix to version specifiers as + Split environment marker, add == prefix to version specifiers as necessary, and remove parenthesis. """ parts = requires_dist.split(';', 1) + [''] @@ -2501,7 +2479,7 @@ class DistInfoDistribution(Distribution): distvers = re.sub(self.EQEQ, r"\1==\2\3", distvers) distvers = distvers.replace('(', '').replace(')', '') return (distvers, mark) - + def _compute_dependencies(self): """Recompute this distribution's dependencies.""" from _markerlib import compile as compile_marker @@ -2514,7 +2492,7 @@ class DistInfoDistribution(Distribution): parsed = parse_requirements(distvers).next() parsed.marker_fn = compile_marker(mark) reqs.append(parsed) - + def reqs_for_extra(extra): for req in reqs: if req.marker_fn(override={'extra':extra}): @@ -2522,13 +2500,13 @@ class DistInfoDistribution(Distribution): common = frozenset(reqs_for_extra(None)) dm[None].extend(common) - + for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: extra = safe_extra(extra.strip()) dm[extra] = list(frozenset(reqs_for_extra(extra)) - common) return dm - + _distributionImpl = {'.egg': Distribution, '.egg-info': Distribution, diff --git a/setuptools/dist.py b/setuptools/dist.py index 6236d5be..998a4dbe 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -242,10 +242,9 @@ class Distribution(_Distribution): """Resolve pre-setup requirements""" from pkg_resources import working_set, parse_requirements for dist in working_set.resolve( - parse_requirements(requires), installer=self.fetch_build_egg, - replace_conflicting=True + parse_requirements(requires), installer=self.fetch_build_egg ): - working_set.add(dist, replace=True) + working_set.add(dist) def finalize_options(self): _Distribution.finalize_options(self) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 2f295b5c..b1799a5a 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -17,10 +17,8 @@ from setuptools.command.easy_install import easy_install, get_script_args, main from setuptools.command.easy_install import PthDistributions from setuptools.command import easy_install as easy_install_pkg from setuptools.dist import Distribution -from pkg_resources import working_set, VersionConflict from pkg_resources import Distribution as PRDistribution import setuptools.tests.server -import pkg_resources try: # import multiprocessing solely for the purpose of testing its existence @@ -275,16 +273,48 @@ class TestUserInstallTest(unittest.TestCase): SandboxViolation. """ - test_pkg = create_setup_requires_package(self.dir) + test_setup_attrs = { + 'name': 'test_pkg', 'version': '0.0', + 'setup_requires': ['foobar'], + 'dependency_links': [os.path.abspath(self.dir)] + } + + test_pkg = os.path.join(self.dir, 'test_pkg') test_setup_py = os.path.join(test_pkg, 'setup.py') + test_setup_cfg = os.path.join(test_pkg, 'setup.cfg') + os.mkdir(test_pkg) + f = open(test_setup_py, 'w') + f.write(textwrap.dedent("""\ + import setuptools + setuptools.setup(**%r) + """ % test_setup_attrs)) + f.close() + + foobar_path = os.path.join(self.dir, 'foobar-0.1.tar.gz') + make_trivial_sdist( + foobar_path, + textwrap.dedent("""\ + import setuptools + setuptools.setup( + name='foobar', + version='0.1' + ) + """)) + + old_stdout = sys.stdout + old_stderr = sys.stderr + sys.stdout = StringIO.StringIO() + sys.stderr = StringIO.StringIO() try: - quiet_context( - lambda: reset_setup_stop_context( - lambda: run_setup(test_setup_py, ['install']) - )) + reset_setup_stop_context( + lambda: run_setup(test_setup_py, ['install']) + ) except SandboxViolation: self.fail('Installation caused SandboxViolation') + finally: + sys.stdout = old_stdout + sys.stderr = old_stderr class TestSetupRequires(unittest.TestCase): @@ -330,7 +360,7 @@ class TestSetupRequires(unittest.TestCase): tempdir_context(install_at) # create an sdist that has a build-time dependency. - quiet_context(lambda: self.create_sdist(install)) + self.create_sdist(install) # there should have been two or three requests to the server # (three happens on Python 3.3a) @@ -357,81 +387,6 @@ class TestSetupRequires(unittest.TestCase): installer(dist_path) tempdir_context(build_sdist) - def test_setup_requires_overrides_version_conflict(self): - """ - Regression test for issue #323. - - Ensures that a distribution's setup_requires requirements can still be - installed and used locally even if a conflicting version of that - requirement is already on the path. - """ - - pr_state = pkg_resources.__getstate__() - fake_dist = PRDistribution('does-not-matter', project_name='foobar', - version='0.0') - working_set.add(fake_dist) - - def setup_and_run(temp_dir): - test_pkg = create_setup_requires_package(temp_dir) - test_setup_py = os.path.join(test_pkg, 'setup.py') - try: - stdout, stderr = quiet_context( - lambda: reset_setup_stop_context( - # Don't even need to install the package, just running - # the setup.py at all is sufficient - lambda: run_setup(test_setup_py, ['--name']) - )) - except VersionConflict: - self.fail('Installing setup.py requirements caused ' - 'VersionConflict') - - lines = stdout.splitlines() - self.assertTrue(len(lines) > 0) - self.assertTrue(lines[-1].strip(), 'test_pkg') - - try: - tempdir_context(setup_and_run) - finally: - pkg_resources.__setstate__(pr_state) - - -def create_setup_requires_package(path): - """Creates a source tree under path for a trivial test package that has a - single requirement in setup_requires--a tarball for that requirement is - also created and added to the dependency_links argument. - """ - - test_setup_attrs = { - 'name': 'test_pkg', 'version': '0.0', - 'setup_requires': ['foobar==0.1'], - 'dependency_links': [os.path.abspath(path)] - } - - test_pkg = os.path.join(path, 'test_pkg') - test_setup_py = os.path.join(test_pkg, 'setup.py') - test_setup_cfg = os.path.join(test_pkg, 'setup.cfg') - os.mkdir(test_pkg) - - f = open(test_setup_py, 'w') - f.write(textwrap.dedent("""\ - import setuptools - setuptools.setup(**%r) - """ % test_setup_attrs)) - f.close() - - foobar_path = os.path.join(path, 'foobar-0.1.tar.gz') - make_trivial_sdist( - foobar_path, - textwrap.dedent("""\ - import setuptools - setuptools.setup( - name='foobar', - version='0.1' - ) - """)) - - return test_pkg - def make_trivial_sdist(dist_path, setup_py): """Create a simple sdist tarball at dist_path, containing just a @@ -466,7 +421,6 @@ def tempdir_context(f, cd=lambda dir:None): cd(orig_dir) shutil.rmtree(temp_dir) - def environment_context(f, **updates): """ Invoke f in the context @@ -480,7 +434,6 @@ def environment_context(f, **updates): del os.environ[key] os.environ.update(old_env) - def argv_context(f, repl): """ Invoke f in the context @@ -492,7 +445,6 @@ def argv_context(f, repl): finally: sys.argv[:] = old_argv - def reset_setup_stop_context(f): """ When the distribute tests are run using setup.py test, and then @@ -506,21 +458,3 @@ def reset_setup_stop_context(f): f() finally: distutils.core._setup_stop_after = setup_stop_after - - -def quiet_context(f): - """ - Redirect stdout/stderr to StringIO objects to prevent console output from - distutils commands. - """ - - old_stdout = sys.stdout - old_stderr = sys.stderr - new_stdout = sys.stdout = StringIO.StringIO() - new_stderr = sys.stderr = StringIO.StringIO() - try: - f() - finally: - sys.stdout = old_stdout - sys.stderr = old_stderr - return new_stdout.getvalue(), new_stderr.getvalue() |