diff options
| author | Jason R. Coombs <jaraco@jaraco.com> | 2016-04-04 08:32:28 -0400 |
|---|---|---|
| committer | Jason R. Coombs <jaraco@jaraco.com> | 2016-04-04 08:32:28 -0400 |
| commit | 48b63f309650af9e43368cf0d6792ea247ad8663 (patch) | |
| tree | 1c9bbeda525f231bd671c9e9f7ea3c3eedcb5854 /pkg_resources/tests/test_resources.py | |
| parent | 1bf92e3a3cc1e246b1ecc05c63287bb177939efa (diff) | |
| parent | 9803058dc72867605bdac20d41249c00e8eae415 (diff) | |
| download | python-setuptools-git-48b63f309650af9e43368cf0d6792ea247ad8663.tar.gz | |
Merge with master
Diffstat (limited to 'pkg_resources/tests/test_resources.py')
| -rw-r--r-- | pkg_resources/tests/test_resources.py | 214 |
1 files changed, 150 insertions, 64 deletions
diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index a55478a2..98b8dcd7 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -1,29 +1,19 @@ +from __future__ import unicode_literals + import os import sys -import tempfile -import shutil import string +from pkg_resources.extern.six.moves import map + import pytest +from pkg_resources.extern import packaging import pkg_resources from pkg_resources import (parse_requirements, VersionConflict, parse_version, Distribution, EntryPoint, Requirement, safe_version, safe_name, WorkingSet) -packaging = pkg_resources.packaging - - -def safe_repr(obj, short=False): - """ copied from Python2.7""" - try: - result = repr(obj) - except Exception: - result = object.__repr__(obj) - if not short or len(result) < pkg_resources._MAX_LENGTH: - return result - return result[:pkg_resources._MAX_LENGTH] + ' [truncated]...' - class Metadata(pkg_resources.EmptyProvider): """Mock object to return metadata as if from an on-disk distribution""" @@ -159,7 +149,7 @@ class TestDistro: for i in range(3): targets = list(ws.resolve(parse_requirements("Foo"), ad)) assert targets == [Foo] - list(map(ws.add,targets)) + list(map(ws.add, targets)) with pytest.raises(VersionConflict): ws.resolve(parse_requirements("Foo==0.9"), ad) ws = WorkingSet([]) # reset @@ -181,6 +171,16 @@ class TestDistro: msg = 'Foo 0.9 is installed but Foo==1.2 is required' assert vc.value.report() == msg + @pytest.mark.xfail(reason="Functionality disabled; see #523") + def test_environment_markers(self): + """ + Environment markers are evaluated at resolution time. + """ + ad = pkg_resources.Environment([]) + ws = WorkingSet([]) + res = ws.resolve(parse_requirements("Foo;python_version<'2'"), ad) + assert list(res) == [] + def testDistroDependsOptions(self): d = self.distRequires(""" Twisted>=1.5 @@ -245,9 +245,8 @@ class TestWorkingSet: with pytest.raises(VersionConflict) as vc: ws.resolve(parse_requirements("Foo\nBar\n")) - msg = "Baz 1.0 is installed but Baz==2.0 is required by {'Bar'}" - if pkg_resources.PY2: - msg = msg.replace("{'Bar'}", "set(['Bar'])") + msg = "Baz 1.0 is installed but Baz==2.0 is required by " + msg += repr(set(['Bar'])) assert vc.value.report() == msg @@ -313,7 +312,7 @@ class TestEntryPoints: def checkSubMap(self, m): assert len(m) == len(self.submap_expect) - for key, ep in pkg_resources.iteritems(self.submap_expect): + for key, ep in self.submap_expect.items(): assert repr(m.get(key)) == repr(ep) submap_expect = dict( @@ -353,22 +352,22 @@ class TestRequirements: r = Requirement.parse("Twisted>=1.2") assert str(r) == "Twisted>=1.2" assert repr(r) == "Requirement.parse('Twisted>=1.2')" - assert r == Requirement("Twisted", [('>=','1.2')], ()) - assert r == Requirement("twisTed", [('>=','1.2')], ()) - assert r != Requirement("Twisted", [('>=','2.0')], ()) - assert r != Requirement("Zope", [('>=','1.2')], ()) - assert r != Requirement("Zope", [('>=','3.0')], ()) - assert r != Requirement.parse("Twisted[extras]>=1.2") + assert r == Requirement("Twisted>=1.2") + assert r == Requirement("twisTed>=1.2") + assert r != Requirement("Twisted>=2.0") + assert r != Requirement("Zope>=1.2") + assert r != Requirement("Zope>=3.0") + assert r != Requirement("Twisted[extras]>=1.2") def testOrdering(self): - r1 = Requirement("Twisted", [('==','1.2c1'),('>=','1.2')], ()) - r2 = Requirement("Twisted", [('>=','1.2'),('==','1.2c1')], ()) + r1 = Requirement("Twisted==1.2c1,>=1.2") + r2 = Requirement("Twisted>=1.2,==1.2c1") assert r1 == r2 assert str(r1) == str(r2) assert str(r2) == "Twisted==1.2c1,>=1.2" def testBasicContains(self): - r = Requirement("Twisted", [('>=','1.2')], ()) + r = Requirement("Twisted>=1.2") foo_dist = Distribution.from_filename("FooPkg-1.3_1.egg") twist11 = Distribution.from_filename("Twisted-1.1.egg") twist12 = Distribution.from_filename("Twisted-1.2.egg") @@ -384,8 +383,8 @@ class TestRequirements: r1 = Requirement.parse("Twisted[foo,bar]>=1.2") r2 = Requirement.parse("Twisted[bar,FOO]>=1.2") assert r1 == r2 - assert r1.extras == ("foo","bar") - assert r2.extras == ("bar","foo") # extras are normalized + assert set(r1.extras) == set(("foo", "bar")) + assert set(r2.extras) == set(("foo", "bar")) assert hash(r1) == hash(r2) assert ( hash(r1) @@ -394,6 +393,7 @@ class TestRequirements: "twisted", packaging.specifiers.SpecifierSet(">=1.2"), frozenset(["foo","bar"]), + None )) ) @@ -485,17 +485,17 @@ class TestParsing: assert ( list(parse_requirements('Twis-Ted>=1.2-1')) == - [Requirement('Twis-Ted',[('>=','1.2-1')], ())] + [Requirement('Twis-Ted>=1.2-1')] ) assert ( list(parse_requirements('Twisted >=1.2, \ # more\n<2.0')) == - [Requirement('Twisted',[('>=','1.2'),('<','2.0')], ())] + [Requirement('Twisted>=1.2,<2.0')] ) assert ( Requirement.parse("FooBar==1.99a3") == - Requirement("FooBar", [('==','1.99a3')], ()) + Requirement("FooBar==1.99a3") ) with pytest.raises(ValueError): Requirement.parse(">=2.3") @@ -508,6 +508,35 @@ class TestParsing: with pytest.raises(ValueError): Requirement.parse("#") + def test_requirements_with_markers(self): + assert ( + Requirement.parse("foobar;os_name=='a'") + == + Requirement.parse("foobar;os_name=='a'") + ) + assert ( + Requirement.parse("name==1.1;python_version=='2.7'") + != + Requirement.parse("name==1.1;python_version=='3.3'") + ) + assert ( + Requirement.parse("name==1.0;python_version=='2.7'") + != + Requirement.parse("name==1.2;python_version=='2.7'") + ) + assert ( + Requirement.parse("name[foo]==1.0;python_version=='3.3'") + != + Requirement.parse("name[foo,bar]==1.0;python_version=='3.3'") + ) + + def test_local_version(self): + req, = parse_requirements('foo==1.0.org1') + + def test_spaces_between_multiple_versions(self): + req, = parse_requirements('foo>=1.0, <3') + req, = parse_requirements('foo >= 1.0, < 3') + def testVersionEquality(self): def c(s1,s2): p1, p2 = parse_version(s1),parse_version(s2) @@ -610,21 +639,44 @@ class TestParsing: class TestNamespaces: - def setup_method(self, method): - self._ns_pkgs = pkg_resources._namespace_packages.copy() - self._tmpdir = tempfile.mkdtemp(prefix="tests-setuptools-") - os.makedirs(os.path.join(self._tmpdir, "site-pkgs")) - self._prev_sys_path = sys.path[:] - sys.path.append(os.path.join(self._tmpdir, "site-pkgs")) - - def teardown_method(self, method): - shutil.rmtree(self._tmpdir) - pkg_resources._namespace_packages = self._ns_pkgs.copy() - sys.path = self._prev_sys_path[:] - - @pytest.mark.skipif(os.path.islink(tempfile.gettempdir()), - reason="Test fails when /tmp is a symlink. See #231") - def test_two_levels_deep(self): + ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n" + + @pytest.yield_fixture + def symlinked_tmpdir(self, tmpdir): + """ + Where available, return the tempdir as a symlink, + which as revealed in #231 is more fragile than + a natural tempdir. + """ + if not hasattr(os, 'symlink'): + yield str(tmpdir) + return + + link_name = str(tmpdir) + '-linked' + os.symlink(str(tmpdir), link_name) + try: + yield type(tmpdir)(link_name) + finally: + os.unlink(link_name) + + @pytest.yield_fixture(autouse=True) + def patched_path(self, tmpdir): + """ + Patch sys.path to include the 'site-pkgs' dir. Also + restore pkg_resources._namespace_packages to its + former state. + """ + saved_ns_pkgs = pkg_resources._namespace_packages.copy() + saved_sys_path = sys.path[:] + site_pkgs = tmpdir.mkdir('site-pkgs') + sys.path.append(str(site_pkgs)) + try: + yield + finally: + pkg_resources._namespace_packages = saved_ns_pkgs + sys.path = saved_sys_path + + def test_two_levels_deep(self, symlinked_tmpdir): """ Test nested namespace packages Create namespace packages in the following tree : @@ -633,19 +685,16 @@ class TestNamespaces: Check both are in the _namespace_packages dict and that their __path__ is correct """ - sys.path.append(os.path.join(self._tmpdir, "site-pkgs2")) - os.makedirs(os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2")) - os.makedirs(os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2")) - ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n" - for site in ["site-pkgs", "site-pkgs2"]: - pkg1_init = open(os.path.join(self._tmpdir, site, - "pkg1", "__init__.py"), "w") - pkg1_init.write(ns_str) - pkg1_init.close() - pkg2_init = open(os.path.join(self._tmpdir, site, - "pkg1", "pkg2", "__init__.py"), "w") - pkg2_init.write(ns_str) - pkg2_init.close() + real_tmpdir = symlinked_tmpdir.realpath() + tmpdir = symlinked_tmpdir + sys.path.append(str(tmpdir / 'site-pkgs2')) + site_dirs = tmpdir / 'site-pkgs', tmpdir / 'site-pkgs2' + for site in site_dirs: + pkg1 = site / 'pkg1' + pkg2 = pkg1 / 'pkg2' + pkg2.ensure_dir() + (pkg1 / '__init__.py').write_text(self.ns_str, encoding='utf-8') + (pkg2 / '__init__.py').write_text(self.ns_str, encoding='utf-8') import pkg1 assert "pkg1" in pkg_resources._namespace_packages # attempt to import pkg2 from site-pkgs2 @@ -655,7 +704,44 @@ class TestNamespaces: assert pkg_resources._namespace_packages["pkg1"] == ["pkg1.pkg2"] # check the __path__ attribute contains both paths expected = [ - os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"), - os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2"), + str(real_tmpdir / "site-pkgs" / "pkg1" / "pkg2"), + str(real_tmpdir / "site-pkgs2" / "pkg1" / "pkg2"), ] assert pkg1.pkg2.__path__ == expected + + def test_path_order(self, symlinked_tmpdir): + """ + Test that if multiple versions of the same namespace package subpackage + are on different sys.path entries, that only the one earliest on + sys.path is imported, and that the namespace package's __path__ is in + the correct order. + + Regression test for https://github.com/pypa/setuptools/issues/207 + """ + + tmpdir = symlinked_tmpdir + site_dirs = ( + tmpdir / "site-pkgs", + tmpdir / "site-pkgs2", + tmpdir / "site-pkgs3", + ) + + vers_str = "__version__ = %r" + + for number, site in enumerate(site_dirs, 1): + if number > 1: + sys.path.append(str(site)) + nspkg = site / 'nspkg' + subpkg = nspkg / 'subpkg' + subpkg.ensure_dir() + (nspkg / '__init__.py').write_text(self.ns_str, encoding='utf-8') + (subpkg / '__init__.py').write_text(vers_str % number, encoding='utf-8') + + import nspkg.subpkg + import nspkg + expected = [ + str(site.realpath() / 'nspkg') + for site in site_dirs + ] + assert nspkg.__path__ == expected + assert nspkg.subpkg.__version__ == 1 |
