ยปCore Development>Code coverage>Lib/lib2to3/fixes/fix_imports.py

Python code coverage for Lib/lib2to3/fixes/fix_imports.py

#countcontent
1n/a"""Fix incompatible imports and module references."""
2n/a# Authors: Collin Winter, Nick Edds
3n/a
4n/a# Local imports
5n/afrom .. import fixer_base
6n/afrom ..fixer_util import Name, attr_chain
7n/a
8n/aMAPPING = {'StringIO': 'io',
9n/a 'cStringIO': 'io',
10n/a 'cPickle': 'pickle',
11n/a '__builtin__' : 'builtins',
12n/a 'copy_reg': 'copyreg',
13n/a 'Queue': 'queue',
14n/a 'SocketServer': 'socketserver',
15n/a 'ConfigParser': 'configparser',
16n/a 'repr': 'reprlib',
17n/a 'FileDialog': 'tkinter.filedialog',
18n/a 'tkFileDialog': 'tkinter.filedialog',
19n/a 'SimpleDialog': 'tkinter.simpledialog',
20n/a 'tkSimpleDialog': 'tkinter.simpledialog',
21n/a 'tkColorChooser': 'tkinter.colorchooser',
22n/a 'tkCommonDialog': 'tkinter.commondialog',
23n/a 'Dialog': 'tkinter.dialog',
24n/a 'Tkdnd': 'tkinter.dnd',
25n/a 'tkFont': 'tkinter.font',
26n/a 'tkMessageBox': 'tkinter.messagebox',
27n/a 'ScrolledText': 'tkinter.scrolledtext',
28n/a 'Tkconstants': 'tkinter.constants',
29n/a 'Tix': 'tkinter.tix',
30n/a 'ttk': 'tkinter.ttk',
31n/a 'Tkinter': 'tkinter',
32n/a 'markupbase': '_markupbase',
33n/a '_winreg': 'winreg',
34n/a 'thread': '_thread',
35n/a 'dummy_thread': '_dummy_thread',
36n/a # anydbm and whichdb are handled by fix_imports2
37n/a 'dbhash': 'dbm.bsd',
38n/a 'dumbdbm': 'dbm.dumb',
39n/a 'dbm': 'dbm.ndbm',
40n/a 'gdbm': 'dbm.gnu',
41n/a 'xmlrpclib': 'xmlrpc.client',
42n/a 'DocXMLRPCServer': 'xmlrpc.server',
43n/a 'SimpleXMLRPCServer': 'xmlrpc.server',
44n/a 'httplib': 'http.client',
45n/a 'htmlentitydefs' : 'html.entities',
46n/a 'HTMLParser' : 'html.parser',
47n/a 'Cookie': 'http.cookies',
48n/a 'cookielib': 'http.cookiejar',
49n/a 'BaseHTTPServer': 'http.server',
50n/a 'SimpleHTTPServer': 'http.server',
51n/a 'CGIHTTPServer': 'http.server',
52n/a #'test.test_support': 'test.support',
53n/a 'commands': 'subprocess',
54n/a 'UserString' : 'collections',
55n/a 'UserList' : 'collections',
56n/a 'urlparse' : 'urllib.parse',
57n/a 'robotparser' : 'urllib.robotparser',
58n/a}
59n/a
60n/a
61n/adef alternates(members):
62n/a return "(" + "|".join(map(repr, members)) + ")"
63n/a
64n/a
65n/adef build_pattern(mapping=MAPPING):
66n/a mod_list = ' | '.join(["module_name='%s'" % key for key in mapping])
67n/a bare_names = alternates(mapping.keys())
68n/a
69n/a yield """name_import=import_name< 'import' ((%s) |
70n/a multiple_imports=dotted_as_names< any* (%s) any* >) >
71n/a """ % (mod_list, mod_list)
72n/a yield """import_from< 'from' (%s) 'import' ['(']
73n/a ( any | import_as_name< any 'as' any > |
74n/a import_as_names< any* >) [')'] >
75n/a """ % mod_list
76n/a yield """import_name< 'import' (dotted_as_name< (%s) 'as' any > |
77n/a multiple_imports=dotted_as_names<
78n/a any* dotted_as_name< (%s) 'as' any > any* >) >
79n/a """ % (mod_list, mod_list)
80n/a
81n/a # Find usages of module members in code e.g. thread.foo(bar)
82n/a yield "power< bare_with_attr=(%s) trailer<'.' any > any* >" % bare_names
83n/a
84n/a
85n/aclass FixImports(fixer_base.BaseFix):
86n/a
87n/a BM_compatible = True
88n/a keep_line_order = True
89n/a # This is overridden in fix_imports2.
90n/a mapping = MAPPING
91n/a
92n/a # We want to run this fixer late, so fix_import doesn't try to make stdlib
93n/a # renames into relative imports.
94n/a run_order = 6
95n/a
96n/a def build_pattern(self):
97n/a return "|".join(build_pattern(self.mapping))
98n/a
99n/a def compile_pattern(self):
100n/a # We override this, so MAPPING can be pragmatically altered and the
101n/a # changes will be reflected in PATTERN.
102n/a self.PATTERN = self.build_pattern()
103n/a super(FixImports, self).compile_pattern()
104n/a
105n/a # Don't match the node if it's within another match.
106n/a def match(self, node):
107n/a match = super(FixImports, self).match
108n/a results = match(node)
109n/a if results:
110n/a # Module usage could be in the trailer of an attribute lookup, so we
111n/a # might have nested matches when "bare_with_attr" is present.
112n/a if "bare_with_attr" not in results and \
113n/a any(match(obj) for obj in attr_chain(node, "parent")):
114n/a return False
115n/a return results
116n/a return False
117n/a
118n/a def start_tree(self, tree, filename):
119n/a super(FixImports, self).start_tree(tree, filename)
120n/a self.replace = {}
121n/a
122n/a def transform(self, node, results):
123n/a import_mod = results.get("module_name")
124n/a if import_mod:
125n/a mod_name = import_mod.value
126n/a new_name = self.mapping[mod_name]
127n/a import_mod.replace(Name(new_name, prefix=import_mod.prefix))
128n/a if "name_import" in results:
129n/a # If it's not a "from x import x, y" or "import x as y" import,
130n/a # marked its usage to be replaced.
131n/a self.replace[mod_name] = new_name
132n/a if "multiple_imports" in results:
133n/a # This is a nasty hack to fix multiple imports on a line (e.g.,
134n/a # "import StringIO, urlparse"). The problem is that I can't
135n/a # figure out an easy way to make a pattern recognize the keys of
136n/a # MAPPING randomly sprinkled in an import statement.
137n/a results = self.match(node)
138n/a if results:
139n/a self.transform(node, results)
140n/a else:
141n/a # Replace usage of the module.
142n/a bare_name = results["bare_with_attr"][0]
143n/a new_name = self.replace.get(bare_name.value)
144n/a if new_name:
145n/a bare_name.replace(Name(new_name, prefix=bare_name.prefix))