1import re 2import textwrap 3import unittest 4 5from collections.abc import Iterator 6 7from . import fixtures 8from importlib.metadata import ( 9 Distribution, PackageNotFoundError, distribution, 10 entry_points, files, metadata, requires, version, 11 ) 12 13 14class APITests( 15 fixtures.EggInfoPkg, 16 fixtures.DistInfoPkg, 17 fixtures.EggInfoFile, 18 unittest.TestCase): 19 20 version_pattern = r'\d+\.\d+(\.\d)?' 21 22 def test_retrieves_version_of_self(self): 23 pkg_version = version('egginfo-pkg') 24 assert isinstance(pkg_version, str) 25 assert re.match(self.version_pattern, pkg_version) 26 27 def test_retrieves_version_of_distinfo_pkg(self): 28 pkg_version = version('distinfo-pkg') 29 assert isinstance(pkg_version, str) 30 assert re.match(self.version_pattern, pkg_version) 31 32 def test_for_name_does_not_exist(self): 33 with self.assertRaises(PackageNotFoundError): 34 distribution('does-not-exist') 35 36 def test_for_top_level(self): 37 self.assertEqual( 38 distribution('egginfo-pkg').read_text('top_level.txt').strip(), 39 'mod') 40 41 def test_read_text(self): 42 top_level = [ 43 path for path in files('egginfo-pkg') 44 if path.name == 'top_level.txt' 45 ][0] 46 self.assertEqual(top_level.read_text(), 'mod\n') 47 48 def test_entry_points(self): 49 entries = dict(entry_points()['entries']) 50 ep = entries['main'] 51 self.assertEqual(ep.value, 'mod:main') 52 self.assertEqual(ep.extras, []) 53 54 def test_metadata_for_this_package(self): 55 md = metadata('egginfo-pkg') 56 assert md['author'] == 'Steven Ma' 57 assert md['LICENSE'] == 'Unknown' 58 assert md['Name'] == 'egginfo-pkg' 59 classifiers = md.get_all('Classifier') 60 assert 'Topic :: Software Development :: Libraries' in classifiers 61 62 @staticmethod 63 def _test_files(files): 64 root = files[0].root 65 for file in files: 66 assert file.root == root 67 assert not file.hash or file.hash.value 68 assert not file.hash or file.hash.mode == 'sha256' 69 assert not file.size or file.size >= 0 70 assert file.locate().exists() 71 assert isinstance(file.read_binary(), bytes) 72 if file.name.endswith('.py'): 73 file.read_text() 74 75 def test_file_hash_repr(self): 76 assertRegex = self.assertRegex 77 78 util = [ 79 p for p in files('distinfo-pkg') 80 if p.name == 'mod.py' 81 ][0] 82 assertRegex( 83 repr(util.hash), 84 '<FileHash mode: sha256 value: .*>') 85 86 def test_files_dist_info(self): 87 self._test_files(files('distinfo-pkg')) 88 89 def test_files_egg_info(self): 90 self._test_files(files('egginfo-pkg')) 91 92 def test_version_egg_info_file(self): 93 self.assertEqual(version('egginfo-file'), '0.1') 94 95 def test_requires_egg_info_file(self): 96 requirements = requires('egginfo-file') 97 self.assertIsNone(requirements) 98 99 def test_requires_egg_info(self): 100 deps = requires('egginfo-pkg') 101 assert len(deps) == 2 102 assert any( 103 dep == 'wheel >= 1.0; python_version >= "2.7"' 104 for dep in deps 105 ) 106 107 def test_requires_dist_info(self): 108 deps = requires('distinfo-pkg') 109 assert len(deps) == 2 110 assert all(deps) 111 assert 'wheel >= 1.0' in deps 112 assert "pytest; extra == 'test'" in deps 113 114 def test_more_complex_deps_requires_text(self): 115 requires = textwrap.dedent(""" 116 dep1 117 dep2 118 119 [:python_version < "3"] 120 dep3 121 122 [extra1] 123 dep4 124 125 [extra2:python_version < "3"] 126 dep5 127 """) 128 deps = sorted(Distribution._deps_from_requires_text(requires)) 129 expected = [ 130 'dep1', 131 'dep2', 132 'dep3; python_version < "3"', 133 'dep4; extra == "extra1"', 134 'dep5; (python_version < "3") and extra == "extra2"', 135 ] 136 # It's important that the environment marker expression be 137 # wrapped in parentheses to avoid the following 'and' binding more 138 # tightly than some other part of the environment expression. 139 140 assert deps == expected 141 142 143class OffSysPathTests(fixtures.DistInfoPkgOffPath, unittest.TestCase): 144 def test_find_distributions_specified_path(self): 145 dists = Distribution.discover(path=[str(self.site_dir)]) 146 assert any( 147 dist.metadata['Name'] == 'distinfo-pkg' 148 for dist in dists 149 ) 150 151 def test_distribution_at_pathlib(self): 152 """Demonstrate how to load metadata direct from a directory. 153 """ 154 dist_info_path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info' 155 dist = Distribution.at(dist_info_path) 156 assert dist.version == '1.0.0' 157 158 def test_distribution_at_str(self): 159 dist_info_path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info' 160 dist = Distribution.at(str(dist_info_path)) 161 assert dist.version == '1.0.0' 162