| """Tests for the packaging.pypi.dist module.""" |
| |
| import os |
| import shutil |
| from packaging.version import VersionPredicate |
| from packaging.pypi.dist import (ReleaseInfo, ReleasesList, DistInfo, |
| split_archive_name, get_infos_from_url) |
| from packaging.pypi.errors import HashDoesNotMatch, UnsupportedHashName |
| |
| from packaging.tests import unittest |
| from packaging.tests.support import TempdirManager, requires_zlib, fake_dec |
| try: |
| import threading |
| from packaging.tests.pypi_server import use_pypi_server |
| except ImportError: |
| threading = None |
| use_pypi_server = fake_dec |
| |
| |
| def Dist(*args, **kwargs): |
| # DistInfo takes a release as a first parameter, avoid this in tests. |
| return DistInfo(None, *args, **kwargs) |
| |
| |
| class TestReleaseInfo(unittest.TestCase): |
| |
| def test_instantiation(self): |
| # Test the DistInfo class provides us the good attributes when |
| # given on construction |
| release = ReleaseInfo("FooBar", "1.1") |
| self.assertEqual("FooBar", release.name) |
| self.assertEqual("1.1", "%s" % release.version) |
| |
| def test_add_dist(self): |
| # empty distribution type should assume "sdist" |
| release = ReleaseInfo("FooBar", "1.1") |
| release.add_distribution(url="http://example.org/") |
| # should not fail |
| release['sdist'] |
| |
| def test_get_unknown_distribution(self): |
| # should raise a KeyError |
| pass |
| |
| def test_get_infos_from_url(self): |
| # Test that the the URLs are parsed the right way |
| url_list = { |
| 'FooBar-1.1.0.tar.gz': { |
| 'name': 'foobar', # lowercase the name |
| 'version': '1.1.0', |
| }, |
| 'Foo-Bar-1.1.0.zip': { |
| 'name': 'foo-bar', # keep the dash |
| 'version': '1.1.0', |
| }, |
| 'foobar-1.1b2.tar.gz#md5=123123123123123': { |
| 'name': 'foobar', |
| 'version': '1.1b2', |
| 'url': 'http://example.org/foobar-1.1b2.tar.gz', # no hash |
| 'hashval': '123123123123123', |
| 'hashname': 'md5', |
| }, |
| 'foobar-1.1-rc2.tar.gz': { # use suggested name |
| 'name': 'foobar', |
| 'version': '1.1c2', |
| 'url': 'http://example.org/foobar-1.1-rc2.tar.gz', |
| } |
| } |
| |
| for url, attributes in url_list.items(): |
| # for each url |
| infos = get_infos_from_url("http://example.org/" + url) |
| for attribute, expected in attributes.items(): |
| got = infos.get(attribute) |
| if attribute == "version": |
| self.assertEqual("%s" % got, expected) |
| else: |
| self.assertEqual(got, expected) |
| |
| def test_split_archive_name(self): |
| # Test we can split the archive names |
| names = { |
| 'foo-bar-baz-1.0-rc2': ('foo-bar-baz', '1.0c2'), |
| 'foo-bar-baz-1.0': ('foo-bar-baz', '1.0'), |
| 'foobarbaz-1.0': ('foobarbaz', '1.0'), |
| } |
| for name, results in names.items(): |
| self.assertEqual(results, split_archive_name(name)) |
| |
| |
| class TestDistInfo(TempdirManager, unittest.TestCase): |
| srcpath = "/packages/source/f/foobar/foobar-0.1.tar.gz" |
| |
| def test_get_url(self): |
| # Test that the url property works well |
| |
| d = Dist(url="test_url") |
| self.assertDictEqual(d.url, { |
| "url": "test_url", |
| "is_external": True, |
| "hashname": None, |
| "hashval": None, |
| }) |
| |
| # add a new url |
| d.add_url(url="internal_url", is_external=False) |
| self.assertEqual(d._url, None) |
| self.assertDictEqual(d.url, { |
| "url": "internal_url", |
| "is_external": False, |
| "hashname": None, |
| "hashval": None, |
| }) |
| self.assertEqual(2, len(d.urls)) |
| |
| def test_comparison(self): |
| # Test that we can compare DistInfoributionInfoList |
| foo1 = ReleaseInfo("foo", "1.0") |
| foo2 = ReleaseInfo("foo", "2.0") |
| bar = ReleaseInfo("bar", "2.0") |
| # assert we use the version to compare |
| self.assertTrue(foo1 < foo2) |
| self.assertFalse(foo1 > foo2) |
| self.assertFalse(foo1 == foo2) |
| |
| # assert we can't compare dists with different names |
| self.assertRaises(TypeError, foo1.__eq__, bar) |
| |
| @unittest.skipIf(threading is None, 'needs threading') |
| @use_pypi_server("downloads_with_md5") |
| def test_download(self, server): |
| # Download is possible, and the md5 is checked if given |
| |
| url = server.full_address + self.srcpath |
| |
| # check that a md5 if given |
| dist = Dist(url=url, hashname="md5", |
| hashval="fe18804c5b722ff024cabdf514924fc4") |
| dist.download(self.mkdtemp()) |
| |
| # a wrong md5 fails |
| dist2 = Dist(url=url, hashname="md5", hashval="wrongmd5") |
| |
| self.assertRaises(HashDoesNotMatch, dist2.download, self.mkdtemp()) |
| |
| # we can omit the md5 hash |
| dist3 = Dist(url=url) |
| dist3.download(self.mkdtemp()) |
| |
| # and specify a temporary location |
| # for an already downloaded dist |
| path1 = self.mkdtemp() |
| dist3.download(path=path1) |
| # and for a new one |
| path2_base = self.mkdtemp() |
| dist4 = Dist(url=url) |
| path2 = dist4.download(path=path2_base) |
| self.assertIn(path2_base, path2) |
| |
| def test_hashname(self): |
| # Invalid hashnames raises an exception on assignation |
| Dist(hashname="md5", hashval="value") |
| |
| self.assertRaises(UnsupportedHashName, Dist, |
| hashname="invalid_hashname", |
| hashval="value") |
| |
| @unittest.skipIf(threading is None, 'needs threading') |
| @requires_zlib |
| @use_pypi_server('downloads_with_md5') |
| def test_unpack(self, server): |
| url = server.full_address + self.srcpath |
| dist1 = Dist(url=url) |
| |
| # unpack the distribution in a specfied folder |
| dist1_here = self.mkdtemp() |
| dist1_there = dist1.unpack(path=dist1_here) |
| |
| # assert we unpack to the path provided |
| self.assertEqual(dist1_here, dist1_there) |
| dist1_result = os.listdir(dist1_there) |
| self.assertIn('paf', dist1_result) |
| os.remove(os.path.join(dist1_there, 'paf')) |
| |
| # Test unpack works without a path argument |
| dist2 = Dist(url=url) |
| # doing an unpack |
| dist2_there = dist2.unpack() |
| self.addCleanup(shutil.rmtree, dist2_there) |
| dist2_result = os.listdir(dist2_there) |
| self.assertIn('paf', dist2_result) |
| os.remove(os.path.join(dist2_there, 'paf')) |
| |
| |
| class TestReleasesList(unittest.TestCase): |
| |
| def test_filter(self): |
| # Test we filter the distributions the right way, using version |
| # predicate match method |
| releases = ReleasesList('FooBar', ( |
| ReleaseInfo("FooBar", "1.1"), |
| ReleaseInfo("FooBar", "1.1.1"), |
| ReleaseInfo("FooBar", "1.2"), |
| ReleaseInfo("FooBar", "1.2.1"), |
| )) |
| filtered = releases.filter(VersionPredicate("FooBar (<1.2)")) |
| self.assertNotIn(releases[2], filtered) |
| self.assertNotIn(releases[3], filtered) |
| self.assertIn(releases[0], filtered) |
| self.assertIn(releases[1], filtered) |
| |
| def test_append(self): |
| # When adding a new item to the list, the behavior is to test if |
| # a release with the same name and version number already exists, |
| # and if so, to add a new distribution for it. If the distribution type |
| # is already defined too, add url informations to the existing DistInfo |
| # object. |
| |
| releases = ReleasesList("FooBar", [ |
| ReleaseInfo("FooBar", "1.1", url="external_url", |
| dist_type="sdist"), |
| ]) |
| self.assertEqual(1, len(releases)) |
| releases.add_release(release=ReleaseInfo("FooBar", "1.1", |
| url="internal_url", |
| is_external=False, |
| dist_type="sdist")) |
| self.assertEqual(1, len(releases)) |
| self.assertEqual(2, len(releases[0]['sdist'].urls)) |
| |
| releases.add_release(release=ReleaseInfo("FooBar", "1.1.1", |
| dist_type="sdist")) |
| self.assertEqual(2, len(releases)) |
| |
| # when adding a distribution whith a different type, a new distribution |
| # has to be added. |
| releases.add_release(release=ReleaseInfo("FooBar", "1.1.1", |
| dist_type="bdist")) |
| self.assertEqual(2, len(releases)) |
| self.assertEqual(2, len(releases[1].dists)) |
| |
| def test_prefer_final(self): |
| # Can order the distributions using prefer_final |
| fb10 = ReleaseInfo("FooBar", "1.0") # final distribution |
| fb11a = ReleaseInfo("FooBar", "1.1a1") # alpha |
| fb12a = ReleaseInfo("FooBar", "1.2a1") # alpha |
| fb12b = ReleaseInfo("FooBar", "1.2b1") # beta |
| dists = ReleasesList("FooBar", [fb10, fb11a, fb12a, fb12b]) |
| |
| dists.sort_releases(prefer_final=True) |
| self.assertEqual(fb10, dists[0]) |
| |
| dists.sort_releases(prefer_final=False) |
| self.assertEqual(fb12b, dists[0]) |
| |
| @unittest.skip('method not implemented yet') |
| def test_prefer_source(self): |
| # Ordering supports prefer_source |
| fb_source = Dist("FooBar", "1.0", type="source") |
| fb_binary = Dist("FooBar", "1.0", type="binary") |
| fb2_binary = Dist("FooBar", "2.0", type="binary") |
| dists = ReleasesList([fb_binary, fb_source]) |
| |
| dists.sort_distributions(prefer_source=True) |
| self.assertEqual(fb_source, dists[0]) |
| |
| dists.sort_distributions(prefer_source=False) |
| self.assertEqual(fb_binary, dists[0]) |
| |
| dists.append(fb2_binary) |
| dists.sort_distributions(prefer_source=True) |
| self.assertEqual(fb2_binary, dists[0]) |
| |
| def test_get_last(self): |
| dists = ReleasesList('Foo') |
| self.assertEqual(dists.get_last('Foo 1.0'), None) |
| |
| |
| def test_suite(): |
| suite = unittest.TestSuite() |
| suite.addTest(unittest.makeSuite(TestDistInfo)) |
| suite.addTest(unittest.makeSuite(TestReleaseInfo)) |
| suite.addTest(unittest.makeSuite(TestReleasesList)) |
| return suite |
| |
| if __name__ == '__main__': |
| unittest.main(defaultTest='test_suite') |