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

Python code coverage for Lib/packaging/tests/fixer/fix_idioms.py

#countcontent
1n/a"""Adjust some old Python 2 idioms to their modern counterparts.
2n/a
3n/a* Change some type comparisons to isinstance() calls:
4n/a type(x) == T -> isinstance(x, T)
5n/a type(x) is T -> isinstance(x, T)
6n/a type(x) != T -> not isinstance(x, T)
7n/a type(x) is not T -> not isinstance(x, T)
8n/a
9n/a* Change "while 1:" into "while True:".
10n/a
11n/a* Change both
12n/a
13n/a v = list(EXPR)
14n/a v.sort()
15n/a foo(v)
16n/a
17n/aand the more general
18n/a
19n/a v = EXPR
20n/a v.sort()
21n/a foo(v)
22n/a
23n/ainto
24n/a
25n/a v = sorted(EXPR)
26n/a foo(v)
27n/a"""
28n/a# Author: Jacques Frechet, Collin Winter
29n/a
30n/a# Local imports
31n/afrom lib2to3 import fixer_base
32n/afrom lib2to3.fixer_util import Call, Comma, Name, Node, syms
33n/a
34n/aCMP = "(n='!=' | '==' | 'is' | n=comp_op< 'is' 'not' >)"
35n/aTYPE = "power< 'type' trailer< '(' x=any ')' > >"
36n/a
37n/aclass FixIdioms(fixer_base.BaseFix):
38n/a
39n/a explicit = False # The user must ask for this fixer
40n/a
41n/a PATTERN = r"""
42n/a isinstance=comparison< %s %s T=any >
43n/a |
44n/a isinstance=comparison< T=any %s %s >
45n/a |
46n/a while_stmt< 'while' while='1' ':' any+ >
47n/a |
48n/a sorted=any<
49n/a any*
50n/a simple_stmt<
51n/a expr_stmt< id1=any '='
52n/a power< list='list' trailer< '(' (not arglist<any+>) any ')' > >
53n/a >
54n/a '\n'
55n/a >
56n/a sort=
57n/a simple_stmt<
58n/a power< id2=any
59n/a trailer< '.' 'sort' > trailer< '(' ')' >
60n/a >
61n/a '\n'
62n/a >
63n/a next=any*
64n/a >
65n/a |
66n/a sorted=any<
67n/a any*
68n/a simple_stmt< expr_stmt< id1=any '=' expr=any > '\n' >
69n/a sort=
70n/a simple_stmt<
71n/a power< id2=any
72n/a trailer< '.' 'sort' > trailer< '(' ')' >
73n/a >
74n/a '\n'
75n/a >
76n/a next=any*
77n/a >
78n/a """ % (TYPE, CMP, CMP, TYPE)
79n/a
80n/a def match(self, node):
81n/a r = super(FixIdioms, self).match(node)
82n/a # If we've matched one of the sort/sorted subpatterns above, we
83n/a # want to reject matches where the initial assignment and the
84n/a # subsequent .sort() call involve different identifiers.
85n/a if r and "sorted" in r:
86n/a if r["id1"] == r["id2"]:
87n/a return r
88n/a return None
89n/a return r
90n/a
91n/a def transform(self, node, results):
92n/a if "isinstance" in results:
93n/a return self.transform_isinstance(node, results)
94n/a elif "while" in results:
95n/a return self.transform_while(node, results)
96n/a elif "sorted" in results:
97n/a return self.transform_sort(node, results)
98n/a else:
99n/a raise RuntimeError("Invalid match")
100n/a
101n/a def transform_isinstance(self, node, results):
102n/a x = results["x"].clone() # The thing inside of type()
103n/a T = results["T"].clone() # The type being compared against
104n/a x.prefix = ""
105n/a T.prefix = " "
106n/a test = Call(Name("isinstance"), [x, Comma(), T])
107n/a if "n" in results:
108n/a test.prefix = " "
109n/a test = Node(syms.not_test, [Name("not"), test])
110n/a test.prefix = node.prefix
111n/a return test
112n/a
113n/a def transform_while(self, node, results):
114n/a one = results["while"]
115n/a one.replace(Name("True", prefix=one.prefix))
116n/a
117n/a def transform_sort(self, node, results):
118n/a sort_stmt = results["sort"]
119n/a next_stmt = results["next"]
120n/a list_call = results.get("list")
121n/a simple_expr = results.get("expr")
122n/a
123n/a if list_call:
124n/a list_call.replace(Name("sorted", prefix=list_call.prefix))
125n/a elif simple_expr:
126n/a new = simple_expr.clone()
127n/a new.prefix = ""
128n/a simple_expr.replace(Call(Name("sorted"), [new],
129n/a prefix=simple_expr.prefix))
130n/a else:
131n/a raise RuntimeError("should not have reached here")
132n/a sort_stmt.remove()
133n/a if next_stmt:
134n/a next_stmt[0].prefix = sort_stmt._prefix