17db96d56Sopenharmony_ci"""Fix changes imports of urllib which are now incompatible. 27db96d56Sopenharmony_ci This is rather similar to fix_imports, but because of the more 37db96d56Sopenharmony_ci complex nature of the fixing for urllib, it has its own fixer. 47db96d56Sopenharmony_ci""" 57db96d56Sopenharmony_ci# Author: Nick Edds 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci# Local imports 87db96d56Sopenharmony_cifrom lib2to3.fixes.fix_imports import alternates, FixImports 97db96d56Sopenharmony_cifrom lib2to3.fixer_util import (Name, Comma, FromImport, Newline, 107db96d56Sopenharmony_ci find_indentation, Node, syms) 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ciMAPPING = {"urllib": [ 137db96d56Sopenharmony_ci ("urllib.request", 147db96d56Sopenharmony_ci ["URLopener", "FancyURLopener", "urlretrieve", 157db96d56Sopenharmony_ci "_urlopener", "urlopen", "urlcleanup", 167db96d56Sopenharmony_ci "pathname2url", "url2pathname", "getproxies"]), 177db96d56Sopenharmony_ci ("urllib.parse", 187db96d56Sopenharmony_ci ["quote", "quote_plus", "unquote", "unquote_plus", 197db96d56Sopenharmony_ci "urlencode", "splitattr", "splithost", "splitnport", 207db96d56Sopenharmony_ci "splitpasswd", "splitport", "splitquery", "splittag", 217db96d56Sopenharmony_ci "splittype", "splituser", "splitvalue", ]), 227db96d56Sopenharmony_ci ("urllib.error", 237db96d56Sopenharmony_ci ["ContentTooShortError"])], 247db96d56Sopenharmony_ci "urllib2" : [ 257db96d56Sopenharmony_ci ("urllib.request", 267db96d56Sopenharmony_ci ["urlopen", "install_opener", "build_opener", 277db96d56Sopenharmony_ci "Request", "OpenerDirector", "BaseHandler", 287db96d56Sopenharmony_ci "HTTPDefaultErrorHandler", "HTTPRedirectHandler", 297db96d56Sopenharmony_ci "HTTPCookieProcessor", "ProxyHandler", 307db96d56Sopenharmony_ci "HTTPPasswordMgr", 317db96d56Sopenharmony_ci "HTTPPasswordMgrWithDefaultRealm", 327db96d56Sopenharmony_ci "AbstractBasicAuthHandler", 337db96d56Sopenharmony_ci "HTTPBasicAuthHandler", "ProxyBasicAuthHandler", 347db96d56Sopenharmony_ci "AbstractDigestAuthHandler", 357db96d56Sopenharmony_ci "HTTPDigestAuthHandler", "ProxyDigestAuthHandler", 367db96d56Sopenharmony_ci "HTTPHandler", "HTTPSHandler", "FileHandler", 377db96d56Sopenharmony_ci "FTPHandler", "CacheFTPHandler", 387db96d56Sopenharmony_ci "UnknownHandler"]), 397db96d56Sopenharmony_ci ("urllib.error", 407db96d56Sopenharmony_ci ["URLError", "HTTPError"]), 417db96d56Sopenharmony_ci ] 427db96d56Sopenharmony_ci} 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci# Duplicate the url parsing functions for urllib2. 457db96d56Sopenharmony_ciMAPPING["urllib2"].append(MAPPING["urllib"][1]) 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_cidef build_pattern(): 497db96d56Sopenharmony_ci bare = set() 507db96d56Sopenharmony_ci for old_module, changes in MAPPING.items(): 517db96d56Sopenharmony_ci for change in changes: 527db96d56Sopenharmony_ci new_module, members = change 537db96d56Sopenharmony_ci members = alternates(members) 547db96d56Sopenharmony_ci yield """import_name< 'import' (module=%r 557db96d56Sopenharmony_ci | dotted_as_names< any* module=%r any* >) > 567db96d56Sopenharmony_ci """ % (old_module, old_module) 577db96d56Sopenharmony_ci yield """import_from< 'from' mod_member=%r 'import' 587db96d56Sopenharmony_ci ( member=%s | import_as_name< member=%s 'as' any > | 597db96d56Sopenharmony_ci import_as_names< members=any* >) > 607db96d56Sopenharmony_ci """ % (old_module, members, members) 617db96d56Sopenharmony_ci yield """import_from< 'from' module_star=%r 'import' star='*' > 627db96d56Sopenharmony_ci """ % old_module 637db96d56Sopenharmony_ci yield """import_name< 'import' 647db96d56Sopenharmony_ci dotted_as_name< module_as=%r 'as' any > > 657db96d56Sopenharmony_ci """ % old_module 667db96d56Sopenharmony_ci # bare_with_attr has a special significance for FixImports.match(). 677db96d56Sopenharmony_ci yield """power< bare_with_attr=%r trailer< '.' member=%s > any* > 687db96d56Sopenharmony_ci """ % (old_module, members) 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ciclass FixUrllib(FixImports): 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci def build_pattern(self): 747db96d56Sopenharmony_ci return "|".join(build_pattern()) 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci def transform_import(self, node, results): 777db96d56Sopenharmony_ci """Transform for the basic import case. Replaces the old 787db96d56Sopenharmony_ci import name with a comma separated list of its 797db96d56Sopenharmony_ci replacements. 807db96d56Sopenharmony_ci """ 817db96d56Sopenharmony_ci import_mod = results.get("module") 827db96d56Sopenharmony_ci pref = import_mod.prefix 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci names = [] 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci # create a Node list of the replacement modules 877db96d56Sopenharmony_ci for name in MAPPING[import_mod.value][:-1]: 887db96d56Sopenharmony_ci names.extend([Name(name[0], prefix=pref), Comma()]) 897db96d56Sopenharmony_ci names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref)) 907db96d56Sopenharmony_ci import_mod.replace(names) 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci def transform_member(self, node, results): 937db96d56Sopenharmony_ci """Transform for imports of specific module elements. Replaces 947db96d56Sopenharmony_ci the module to be imported from with the appropriate new 957db96d56Sopenharmony_ci module. 967db96d56Sopenharmony_ci """ 977db96d56Sopenharmony_ci mod_member = results.get("mod_member") 987db96d56Sopenharmony_ci pref = mod_member.prefix 997db96d56Sopenharmony_ci member = results.get("member") 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci # Simple case with only a single member being imported 1027db96d56Sopenharmony_ci if member: 1037db96d56Sopenharmony_ci # this may be a list of length one, or just a node 1047db96d56Sopenharmony_ci if isinstance(member, list): 1057db96d56Sopenharmony_ci member = member[0] 1067db96d56Sopenharmony_ci new_name = None 1077db96d56Sopenharmony_ci for change in MAPPING[mod_member.value]: 1087db96d56Sopenharmony_ci if member.value in change[1]: 1097db96d56Sopenharmony_ci new_name = change[0] 1107db96d56Sopenharmony_ci break 1117db96d56Sopenharmony_ci if new_name: 1127db96d56Sopenharmony_ci mod_member.replace(Name(new_name, prefix=pref)) 1137db96d56Sopenharmony_ci else: 1147db96d56Sopenharmony_ci self.cannot_convert(node, "This is an invalid module element") 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_ci # Multiple members being imported 1177db96d56Sopenharmony_ci else: 1187db96d56Sopenharmony_ci # a dictionary for replacements, order matters 1197db96d56Sopenharmony_ci modules = [] 1207db96d56Sopenharmony_ci mod_dict = {} 1217db96d56Sopenharmony_ci members = results["members"] 1227db96d56Sopenharmony_ci for member in members: 1237db96d56Sopenharmony_ci # we only care about the actual members 1247db96d56Sopenharmony_ci if member.type == syms.import_as_name: 1257db96d56Sopenharmony_ci as_name = member.children[2].value 1267db96d56Sopenharmony_ci member_name = member.children[0].value 1277db96d56Sopenharmony_ci else: 1287db96d56Sopenharmony_ci member_name = member.value 1297db96d56Sopenharmony_ci as_name = None 1307db96d56Sopenharmony_ci if member_name != ",": 1317db96d56Sopenharmony_ci for change in MAPPING[mod_member.value]: 1327db96d56Sopenharmony_ci if member_name in change[1]: 1337db96d56Sopenharmony_ci if change[0] not in mod_dict: 1347db96d56Sopenharmony_ci modules.append(change[0]) 1357db96d56Sopenharmony_ci mod_dict.setdefault(change[0], []).append(member) 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ci new_nodes = [] 1387db96d56Sopenharmony_ci indentation = find_indentation(node) 1397db96d56Sopenharmony_ci first = True 1407db96d56Sopenharmony_ci def handle_name(name, prefix): 1417db96d56Sopenharmony_ci if name.type == syms.import_as_name: 1427db96d56Sopenharmony_ci kids = [Name(name.children[0].value, prefix=prefix), 1437db96d56Sopenharmony_ci name.children[1].clone(), 1447db96d56Sopenharmony_ci name.children[2].clone()] 1457db96d56Sopenharmony_ci return [Node(syms.import_as_name, kids)] 1467db96d56Sopenharmony_ci return [Name(name.value, prefix=prefix)] 1477db96d56Sopenharmony_ci for module in modules: 1487db96d56Sopenharmony_ci elts = mod_dict[module] 1497db96d56Sopenharmony_ci names = [] 1507db96d56Sopenharmony_ci for elt in elts[:-1]: 1517db96d56Sopenharmony_ci names.extend(handle_name(elt, pref)) 1527db96d56Sopenharmony_ci names.append(Comma()) 1537db96d56Sopenharmony_ci names.extend(handle_name(elts[-1], pref)) 1547db96d56Sopenharmony_ci new = FromImport(module, names) 1557db96d56Sopenharmony_ci if not first or node.parent.prefix.endswith(indentation): 1567db96d56Sopenharmony_ci new.prefix = indentation 1577db96d56Sopenharmony_ci new_nodes.append(new) 1587db96d56Sopenharmony_ci first = False 1597db96d56Sopenharmony_ci if new_nodes: 1607db96d56Sopenharmony_ci nodes = [] 1617db96d56Sopenharmony_ci for new_node in new_nodes[:-1]: 1627db96d56Sopenharmony_ci nodes.extend([new_node, Newline()]) 1637db96d56Sopenharmony_ci nodes.append(new_nodes[-1]) 1647db96d56Sopenharmony_ci node.replace(nodes) 1657db96d56Sopenharmony_ci else: 1667db96d56Sopenharmony_ci self.cannot_convert(node, "All module elements are invalid") 1677db96d56Sopenharmony_ci 1687db96d56Sopenharmony_ci def transform_dot(self, node, results): 1697db96d56Sopenharmony_ci """Transform for calls to module members in code.""" 1707db96d56Sopenharmony_ci module_dot = results.get("bare_with_attr") 1717db96d56Sopenharmony_ci member = results.get("member") 1727db96d56Sopenharmony_ci new_name = None 1737db96d56Sopenharmony_ci if isinstance(member, list): 1747db96d56Sopenharmony_ci member = member[0] 1757db96d56Sopenharmony_ci for change in MAPPING[module_dot.value]: 1767db96d56Sopenharmony_ci if member.value in change[1]: 1777db96d56Sopenharmony_ci new_name = change[0] 1787db96d56Sopenharmony_ci break 1797db96d56Sopenharmony_ci if new_name: 1807db96d56Sopenharmony_ci module_dot.replace(Name(new_name, 1817db96d56Sopenharmony_ci prefix=module_dot.prefix)) 1827db96d56Sopenharmony_ci else: 1837db96d56Sopenharmony_ci self.cannot_convert(node, "This is an invalid module element") 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci def transform(self, node, results): 1867db96d56Sopenharmony_ci if results.get("module"): 1877db96d56Sopenharmony_ci self.transform_import(node, results) 1887db96d56Sopenharmony_ci elif results.get("mod_member"): 1897db96d56Sopenharmony_ci self.transform_member(node, results) 1907db96d56Sopenharmony_ci elif results.get("bare_with_attr"): 1917db96d56Sopenharmony_ci self.transform_dot(node, results) 1927db96d56Sopenharmony_ci # Renaming and star imports are not supported for these modules. 1937db96d56Sopenharmony_ci elif results.get("module_star"): 1947db96d56Sopenharmony_ci self.cannot_convert(node, "Cannot handle star imports.") 1957db96d56Sopenharmony_ci elif results.get("module_as"): 1967db96d56Sopenharmony_ci self.cannot_convert(node, "This module is now multiple modules") 197