ยปCore Development>Code coverage>Lib/packaging/tests/test_depgraph.py

Python code coverage for Lib/packaging/tests/test_depgraph.py

#countcontent
1n/a"""Tests for packaging.depgraph """
2n/aimport os
3n/aimport re
4n/aimport sys
5n/afrom io import StringIO
6n/a
7n/afrom packaging import depgraph
8n/afrom packaging.database import get_distribution, enable_cache, disable_cache
9n/a
10n/afrom packaging.tests import unittest, support
11n/afrom packaging.tests.support import requires_zlib
12n/a
13n/a
14n/aclass DepGraphTestCase(support.LoggingCatcher,
15n/a unittest.TestCase):
16n/a
17n/a DISTROS_DIST = ('choxie', 'grammar', 'towel-stuff')
18n/a DISTROS_EGG = ('bacon', 'banana', 'strawberry', 'cheese')
19n/a BAD_EGGS = ('nut',)
20n/a
21n/a EDGE = re.compile(
22n/a r'"(?P<from>.*)" -> "(?P<to>.*)" \[label="(?P<label>.*)"\]')
23n/a
24n/a def checkLists(self, l1, l2):
25n/a """ Compare two lists without taking the order into consideration """
26n/a self.assertListEqual(sorted(l1), sorted(l2))
27n/a
28n/a def setUp(self):
29n/a super(DepGraphTestCase, self).setUp()
30n/a path = os.path.join(os.path.dirname(__file__), 'fake_dists')
31n/a path = os.path.abspath(path)
32n/a sys.path.insert(0, path)
33n/a self.addCleanup(sys.path.remove, path)
34n/a self.addCleanup(enable_cache)
35n/a disable_cache()
36n/a
37n/a def test_generate_graph(self):
38n/a dists = []
39n/a for name in self.DISTROS_DIST:
40n/a dist = get_distribution(name)
41n/a self.assertNotEqual(dist, None)
42n/a dists.append(dist)
43n/a
44n/a choxie, grammar, towel = dists
45n/a
46n/a graph = depgraph.generate_graph(dists)
47n/a
48n/a deps = [(x.name, y) for x, y in graph.adjacency_list[choxie]]
49n/a self.checkLists([('towel-stuff', 'towel-stuff (0.1)')], deps)
50n/a self.assertIn(choxie, graph.reverse_list[towel])
51n/a self.checkLists(graph.missing[choxie], ['nut'])
52n/a
53n/a deps = [(x.name, y) for x, y in graph.adjacency_list[grammar]]
54n/a self.checkLists([], deps)
55n/a self.checkLists(graph.missing[grammar], ['truffles (>=1.2)'])
56n/a
57n/a deps = [(x.name, y) for x, y in graph.adjacency_list[towel]]
58n/a self.checkLists([], deps)
59n/a self.checkLists(graph.missing[towel], ['bacon (<=0.2)'])
60n/a
61n/a @requires_zlib
62n/a def test_generate_graph_egg(self):
63n/a dists = []
64n/a for name in self.DISTROS_DIST + self.DISTROS_EGG:
65n/a dist = get_distribution(name, use_egg_info=True)
66n/a self.assertNotEqual(dist, None)
67n/a dists.append(dist)
68n/a
69n/a choxie, grammar, towel, bacon, banana, strawberry, cheese = dists
70n/a
71n/a graph = depgraph.generate_graph(dists)
72n/a
73n/a deps = [(x.name, y) for x, y in graph.adjacency_list[choxie]]
74n/a self.checkLists([('towel-stuff', 'towel-stuff (0.1)')], deps)
75n/a self.assertIn(choxie, graph.reverse_list[towel])
76n/a self.checkLists(graph.missing[choxie], ['nut'])
77n/a
78n/a deps = [(x.name, y) for x, y in graph.adjacency_list[grammar]]
79n/a self.checkLists([('bacon', 'truffles (>=1.2)')], deps)
80n/a self.checkLists(graph.missing[grammar], [])
81n/a self.assertIn(grammar, graph.reverse_list[bacon])
82n/a
83n/a deps = [(x.name, y) for x, y in graph.adjacency_list[towel]]
84n/a self.checkLists([('bacon', 'bacon (<=0.2)')], deps)
85n/a self.checkLists(graph.missing[towel], [])
86n/a self.assertIn(towel, graph.reverse_list[bacon])
87n/a
88n/a deps = [(x.name, y) for x, y in graph.adjacency_list[bacon]]
89n/a self.checkLists([], deps)
90n/a self.checkLists(graph.missing[bacon], [])
91n/a
92n/a deps = [(x.name, y) for x, y in graph.adjacency_list[banana]]
93n/a self.checkLists([('strawberry', 'strawberry (>=0.5)')], deps)
94n/a self.checkLists(graph.missing[banana], [])
95n/a self.assertIn(banana, graph.reverse_list[strawberry])
96n/a
97n/a deps = [(x.name, y) for x, y in graph.adjacency_list[strawberry]]
98n/a self.checkLists([], deps)
99n/a self.checkLists(graph.missing[strawberry], [])
100n/a
101n/a deps = [(x.name, y) for x, y in graph.adjacency_list[cheese]]
102n/a self.checkLists([], deps)
103n/a self.checkLists(graph.missing[cheese], [])
104n/a
105n/a def test_dependent_dists(self):
106n/a dists = []
107n/a for name in self.DISTROS_DIST:
108n/a dist = get_distribution(name)
109n/a self.assertNotEqual(dist, None)
110n/a dists.append(dist)
111n/a
112n/a choxie, grammar, towel = dists
113n/a
114n/a deps = [d.name for d in depgraph.dependent_dists(dists, choxie)]
115n/a self.checkLists([], deps)
116n/a
117n/a deps = [d.name for d in depgraph.dependent_dists(dists, grammar)]
118n/a self.checkLists([], deps)
119n/a
120n/a deps = [d.name for d in depgraph.dependent_dists(dists, towel)]
121n/a self.checkLists(['choxie'], deps)
122n/a
123n/a @requires_zlib
124n/a def test_dependent_dists_egg(self):
125n/a dists = []
126n/a for name in self.DISTROS_DIST + self.DISTROS_EGG:
127n/a dist = get_distribution(name, use_egg_info=True)
128n/a self.assertNotEqual(dist, None)
129n/a dists.append(dist)
130n/a
131n/a choxie, grammar, towel, bacon, banana, strawberry, cheese = dists
132n/a
133n/a deps = [d.name for d in depgraph.dependent_dists(dists, choxie)]
134n/a self.checkLists([], deps)
135n/a
136n/a deps = [d.name for d in depgraph.dependent_dists(dists, grammar)]
137n/a self.checkLists([], deps)
138n/a
139n/a deps = [d.name for d in depgraph.dependent_dists(dists, towel)]
140n/a self.checkLists(['choxie'], deps)
141n/a
142n/a deps = [d.name for d in depgraph.dependent_dists(dists, bacon)]
143n/a self.checkLists(['choxie', 'towel-stuff', 'grammar'], deps)
144n/a
145n/a deps = [d.name for d in depgraph.dependent_dists(dists, strawberry)]
146n/a self.checkLists(['banana'], deps)
147n/a
148n/a deps = [d.name for d in depgraph.dependent_dists(dists, cheese)]
149n/a self.checkLists([], deps)
150n/a
151n/a @requires_zlib
152n/a def test_graph_to_dot(self):
153n/a expected = (
154n/a ('towel-stuff', 'bacon', 'bacon (<=0.2)'),
155n/a ('grammar', 'bacon', 'truffles (>=1.2)'),
156n/a ('choxie', 'towel-stuff', 'towel-stuff (0.1)'),
157n/a ('banana', 'strawberry', 'strawberry (>=0.5)'),
158n/a )
159n/a
160n/a dists = []
161n/a for name in self.DISTROS_DIST + self.DISTROS_EGG:
162n/a dist = get_distribution(name, use_egg_info=True)
163n/a self.assertNotEqual(dist, None)
164n/a dists.append(dist)
165n/a
166n/a graph = depgraph.generate_graph(dists)
167n/a buf = StringIO()
168n/a depgraph.graph_to_dot(graph, buf)
169n/a buf.seek(0)
170n/a matches = []
171n/a lines = buf.readlines()
172n/a for line in lines[1:-1]: # skip the first and the last lines
173n/a if line[-1] == '\n':
174n/a line = line[:-1]
175n/a match = self.EDGE.match(line.strip())
176n/a self.assertIsNot(match, None)
177n/a matches.append(match.groups())
178n/a
179n/a self.checkLists(matches, expected)
180n/a
181n/a @requires_zlib
182n/a def test_graph_disconnected_to_dot(self):
183n/a dependencies_expected = (
184n/a ('towel-stuff', 'bacon', 'bacon (<=0.2)'),
185n/a ('grammar', 'bacon', 'truffles (>=1.2)'),
186n/a ('choxie', 'towel-stuff', 'towel-stuff (0.1)'),
187n/a ('banana', 'strawberry', 'strawberry (>=0.5)'),
188n/a )
189n/a disconnected_expected = ('cheese', 'bacon', 'strawberry')
190n/a
191n/a dists = []
192n/a for name in self.DISTROS_DIST + self.DISTROS_EGG:
193n/a dist = get_distribution(name, use_egg_info=True)
194n/a self.assertNotEqual(dist, None)
195n/a dists.append(dist)
196n/a
197n/a graph = depgraph.generate_graph(dists)
198n/a buf = StringIO()
199n/a depgraph.graph_to_dot(graph, buf, skip_disconnected=False)
200n/a buf.seek(0)
201n/a lines = buf.readlines()
202n/a
203n/a dependencies_lines = []
204n/a disconnected_lines = []
205n/a
206n/a # First sort output lines into dependencies and disconnected lines.
207n/a # We also skip the attribute lines, and don't include the "{" and "}"
208n/a # lines.
209n/a disconnected_active = False
210n/a for line in lines[1:-1]: # Skip first and last line
211n/a if line.startswith('subgraph disconnected'):
212n/a disconnected_active = True
213n/a continue
214n/a if line.startswith('}') and disconnected_active:
215n/a disconnected_active = False
216n/a continue
217n/a
218n/a if disconnected_active:
219n/a # Skip the 'label = "Disconnected"', etc. attribute lines.
220n/a if ' = ' not in line:
221n/a disconnected_lines.append(line)
222n/a else:
223n/a dependencies_lines.append(line)
224n/a
225n/a dependencies_matches = []
226n/a for line in dependencies_lines:
227n/a if line[-1] == '\n':
228n/a line = line[:-1]
229n/a match = self.EDGE.match(line.strip())
230n/a self.assertIsNot(match, None)
231n/a dependencies_matches.append(match.groups())
232n/a
233n/a disconnected_matches = []
234n/a for line in disconnected_lines:
235n/a if line[-1] == '\n':
236n/a line = line[:-1]
237n/a line = line.strip('"')
238n/a disconnected_matches.append(line)
239n/a
240n/a self.checkLists(dependencies_matches, dependencies_expected)
241n/a self.checkLists(disconnected_matches, disconnected_expected)
242n/a
243n/a @requires_zlib
244n/a def test_graph_bad_version_to_dot(self):
245n/a expected = (
246n/a ('towel-stuff', 'bacon', 'bacon (<=0.2)'),
247n/a ('grammar', 'bacon', 'truffles (>=1.2)'),
248n/a ('choxie', 'towel-stuff', 'towel-stuff (0.1)'),
249n/a ('banana', 'strawberry', 'strawberry (>=0.5)'),
250n/a )
251n/a
252n/a dists = []
253n/a for name in self.DISTROS_DIST + self.DISTROS_EGG + self.BAD_EGGS:
254n/a dist = get_distribution(name, use_egg_info=True)
255n/a self.assertNotEqual(dist, None)
256n/a dists.append(dist)
257n/a
258n/a graph = depgraph.generate_graph(dists)
259n/a buf = StringIO()
260n/a depgraph.graph_to_dot(graph, buf)
261n/a buf.seek(0)
262n/a matches = []
263n/a lines = buf.readlines()
264n/a for line in lines[1:-1]: # skip the first and the last lines
265n/a if line[-1] == '\n':
266n/a line = line[:-1]
267n/a match = self.EDGE.match(line.strip())
268n/a self.assertIsNot(match, None)
269n/a matches.append(match.groups())
270n/a
271n/a self.checkLists(matches, expected)
272n/a
273n/a @requires_zlib
274n/a def test_repr(self):
275n/a dists = []
276n/a for name in self.DISTROS_DIST + self.DISTROS_EGG + self.BAD_EGGS:
277n/a dist = get_distribution(name, use_egg_info=True)
278n/a self.assertNotEqual(dist, None)
279n/a dists.append(dist)
280n/a
281n/a graph = depgraph.generate_graph(dists)
282n/a self.assertTrue(repr(graph))
283n/a
284n/a @requires_zlib
285n/a def test_main(self):
286n/a tempout = StringIO()
287n/a old = sys.stdout
288n/a sys.stdout = tempout
289n/a oldargv = sys.argv[:]
290n/a sys.argv[:] = ['script.py']
291n/a try:
292n/a try:
293n/a depgraph.main()
294n/a except SystemExit:
295n/a pass
296n/a finally:
297n/a sys.stdout = old
298n/a sys.argv[:] = oldargv
299n/a
300n/a # checks what main did XXX could do more here
301n/a tempout.seek(0)
302n/a res = tempout.read()
303n/a self.assertIn('towel', res)
304n/a
305n/a
306n/adef test_suite():
307n/a return unittest.makeSuite(DepGraphTestCase)
308n/a
309n/aif __name__ == "__main__":
310n/a unittest.main(defaultTest="test_suite")