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