• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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