17db96d56Sopenharmony_ci"""Fix incompatible imports and module references.""" 27db96d56Sopenharmony_ci# Authors: Collin Winter, Nick Edds 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci# Local imports 57db96d56Sopenharmony_cifrom .. import fixer_base 67db96d56Sopenharmony_cifrom ..fixer_util import Name, attr_chain 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ciMAPPING = {'StringIO': 'io', 97db96d56Sopenharmony_ci 'cStringIO': 'io', 107db96d56Sopenharmony_ci 'cPickle': 'pickle', 117db96d56Sopenharmony_ci '__builtin__' : 'builtins', 127db96d56Sopenharmony_ci 'copy_reg': 'copyreg', 137db96d56Sopenharmony_ci 'Queue': 'queue', 147db96d56Sopenharmony_ci 'SocketServer': 'socketserver', 157db96d56Sopenharmony_ci 'ConfigParser': 'configparser', 167db96d56Sopenharmony_ci 'repr': 'reprlib', 177db96d56Sopenharmony_ci 'FileDialog': 'tkinter.filedialog', 187db96d56Sopenharmony_ci 'tkFileDialog': 'tkinter.filedialog', 197db96d56Sopenharmony_ci 'SimpleDialog': 'tkinter.simpledialog', 207db96d56Sopenharmony_ci 'tkSimpleDialog': 'tkinter.simpledialog', 217db96d56Sopenharmony_ci 'tkColorChooser': 'tkinter.colorchooser', 227db96d56Sopenharmony_ci 'tkCommonDialog': 'tkinter.commondialog', 237db96d56Sopenharmony_ci 'Dialog': 'tkinter.dialog', 247db96d56Sopenharmony_ci 'Tkdnd': 'tkinter.dnd', 257db96d56Sopenharmony_ci 'tkFont': 'tkinter.font', 267db96d56Sopenharmony_ci 'tkMessageBox': 'tkinter.messagebox', 277db96d56Sopenharmony_ci 'ScrolledText': 'tkinter.scrolledtext', 287db96d56Sopenharmony_ci 'Tkconstants': 'tkinter.constants', 297db96d56Sopenharmony_ci 'Tix': 'tkinter.tix', 307db96d56Sopenharmony_ci 'ttk': 'tkinter.ttk', 317db96d56Sopenharmony_ci 'Tkinter': 'tkinter', 327db96d56Sopenharmony_ci 'markupbase': '_markupbase', 337db96d56Sopenharmony_ci '_winreg': 'winreg', 347db96d56Sopenharmony_ci 'thread': '_thread', 357db96d56Sopenharmony_ci 'dummy_thread': '_dummy_thread', 367db96d56Sopenharmony_ci # anydbm and whichdb are handled by fix_imports2 377db96d56Sopenharmony_ci 'dbhash': 'dbm.bsd', 387db96d56Sopenharmony_ci 'dumbdbm': 'dbm.dumb', 397db96d56Sopenharmony_ci 'dbm': 'dbm.ndbm', 407db96d56Sopenharmony_ci 'gdbm': 'dbm.gnu', 417db96d56Sopenharmony_ci 'xmlrpclib': 'xmlrpc.client', 427db96d56Sopenharmony_ci 'DocXMLRPCServer': 'xmlrpc.server', 437db96d56Sopenharmony_ci 'SimpleXMLRPCServer': 'xmlrpc.server', 447db96d56Sopenharmony_ci 'httplib': 'http.client', 457db96d56Sopenharmony_ci 'htmlentitydefs' : 'html.entities', 467db96d56Sopenharmony_ci 'HTMLParser' : 'html.parser', 477db96d56Sopenharmony_ci 'Cookie': 'http.cookies', 487db96d56Sopenharmony_ci 'cookielib': 'http.cookiejar', 497db96d56Sopenharmony_ci 'BaseHTTPServer': 'http.server', 507db96d56Sopenharmony_ci 'SimpleHTTPServer': 'http.server', 517db96d56Sopenharmony_ci 'CGIHTTPServer': 'http.server', 527db96d56Sopenharmony_ci #'test.test_support': 'test.support', 537db96d56Sopenharmony_ci 'commands': 'subprocess', 547db96d56Sopenharmony_ci 'UserString' : 'collections', 557db96d56Sopenharmony_ci 'UserList' : 'collections', 567db96d56Sopenharmony_ci 'urlparse' : 'urllib.parse', 577db96d56Sopenharmony_ci 'robotparser' : 'urllib.robotparser', 587db96d56Sopenharmony_ci} 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_cidef alternates(members): 627db96d56Sopenharmony_ci return "(" + "|".join(map(repr, members)) + ")" 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_cidef build_pattern(mapping=MAPPING): 667db96d56Sopenharmony_ci mod_list = ' | '.join(["module_name='%s'" % key for key in mapping]) 677db96d56Sopenharmony_ci bare_names = alternates(mapping.keys()) 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci yield """name_import=import_name< 'import' ((%s) | 707db96d56Sopenharmony_ci multiple_imports=dotted_as_names< any* (%s) any* >) > 717db96d56Sopenharmony_ci """ % (mod_list, mod_list) 727db96d56Sopenharmony_ci yield """import_from< 'from' (%s) 'import' ['('] 737db96d56Sopenharmony_ci ( any | import_as_name< any 'as' any > | 747db96d56Sopenharmony_ci import_as_names< any* >) [')'] > 757db96d56Sopenharmony_ci """ % mod_list 767db96d56Sopenharmony_ci yield """import_name< 'import' (dotted_as_name< (%s) 'as' any > | 777db96d56Sopenharmony_ci multiple_imports=dotted_as_names< 787db96d56Sopenharmony_ci any* dotted_as_name< (%s) 'as' any > any* >) > 797db96d56Sopenharmony_ci """ % (mod_list, mod_list) 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci # Find usages of module members in code e.g. thread.foo(bar) 827db96d56Sopenharmony_ci yield "power< bare_with_attr=(%s) trailer<'.' any > any* >" % bare_names 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_ciclass FixImports(fixer_base.BaseFix): 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci BM_compatible = True 887db96d56Sopenharmony_ci keep_line_order = True 897db96d56Sopenharmony_ci # This is overridden in fix_imports2. 907db96d56Sopenharmony_ci mapping = MAPPING 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci # We want to run this fixer late, so fix_import doesn't try to make stdlib 937db96d56Sopenharmony_ci # renames into relative imports. 947db96d56Sopenharmony_ci run_order = 6 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci def build_pattern(self): 977db96d56Sopenharmony_ci return "|".join(build_pattern(self.mapping)) 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci def compile_pattern(self): 1007db96d56Sopenharmony_ci # We override this, so MAPPING can be pragmatically altered and the 1017db96d56Sopenharmony_ci # changes will be reflected in PATTERN. 1027db96d56Sopenharmony_ci self.PATTERN = self.build_pattern() 1037db96d56Sopenharmony_ci super(FixImports, self).compile_pattern() 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci # Don't match the node if it's within another match. 1067db96d56Sopenharmony_ci def match(self, node): 1077db96d56Sopenharmony_ci match = super(FixImports, self).match 1087db96d56Sopenharmony_ci results = match(node) 1097db96d56Sopenharmony_ci if results: 1107db96d56Sopenharmony_ci # Module usage could be in the trailer of an attribute lookup, so we 1117db96d56Sopenharmony_ci # might have nested matches when "bare_with_attr" is present. 1127db96d56Sopenharmony_ci if "bare_with_attr" not in results and \ 1137db96d56Sopenharmony_ci any(match(obj) for obj in attr_chain(node, "parent")): 1147db96d56Sopenharmony_ci return False 1157db96d56Sopenharmony_ci return results 1167db96d56Sopenharmony_ci return False 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci def start_tree(self, tree, filename): 1197db96d56Sopenharmony_ci super(FixImports, self).start_tree(tree, filename) 1207db96d56Sopenharmony_ci self.replace = {} 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci def transform(self, node, results): 1237db96d56Sopenharmony_ci import_mod = results.get("module_name") 1247db96d56Sopenharmony_ci if import_mod: 1257db96d56Sopenharmony_ci mod_name = import_mod.value 1267db96d56Sopenharmony_ci new_name = self.mapping[mod_name] 1277db96d56Sopenharmony_ci import_mod.replace(Name(new_name, prefix=import_mod.prefix)) 1287db96d56Sopenharmony_ci if "name_import" in results: 1297db96d56Sopenharmony_ci # If it's not a "from x import x, y" or "import x as y" import, 1307db96d56Sopenharmony_ci # marked its usage to be replaced. 1317db96d56Sopenharmony_ci self.replace[mod_name] = new_name 1327db96d56Sopenharmony_ci if "multiple_imports" in results: 1337db96d56Sopenharmony_ci # This is a nasty hack to fix multiple imports on a line (e.g., 1347db96d56Sopenharmony_ci # "import StringIO, urlparse"). The problem is that I can't 1357db96d56Sopenharmony_ci # figure out an easy way to make a pattern recognize the keys of 1367db96d56Sopenharmony_ci # MAPPING randomly sprinkled in an import statement. 1377db96d56Sopenharmony_ci results = self.match(node) 1387db96d56Sopenharmony_ci if results: 1397db96d56Sopenharmony_ci self.transform(node, results) 1407db96d56Sopenharmony_ci else: 1417db96d56Sopenharmony_ci # Replace usage of the module. 1427db96d56Sopenharmony_ci bare_name = results["bare_with_attr"][0] 1437db96d56Sopenharmony_ci new_name = self.replace.get(bare_name.value) 1447db96d56Sopenharmony_ci if new_name: 1457db96d56Sopenharmony_ci bare_name.replace(Name(new_name, prefix=bare_name.prefix)) 146