123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- """Fix changes imports of urllib which are now incompatible.
- This is rather similar to fix_imports, but because of the more
- complex nature of the fixing for urllib, it has its own fixer.
- """
- # Author: Nick Edds
- # Local imports
- from lib2to3.fixes.fix_imports import alternates, FixImports
- from lib2to3.fixer_util import (Name, Comma, FromImport, Newline,
- find_indentation, Node, syms)
- MAPPING = {"urllib": [
- ("urllib.request",
- ["URLopener", "FancyURLopener", "urlretrieve",
- "_urlopener", "urlopen", "urlcleanup",
- "pathname2url", "url2pathname", "getproxies"]),
- ("urllib.parse",
- ["quote", "quote_plus", "unquote", "unquote_plus",
- "urlencode", "splitattr", "splithost", "splitnport",
- "splitpasswd", "splitport", "splitquery", "splittag",
- "splittype", "splituser", "splitvalue", ]),
- ("urllib.error",
- ["ContentTooShortError"])],
- "urllib2" : [
- ("urllib.request",
- ["urlopen", "install_opener", "build_opener",
- "Request", "OpenerDirector", "BaseHandler",
- "HTTPDefaultErrorHandler", "HTTPRedirectHandler",
- "HTTPCookieProcessor", "ProxyHandler",
- "HTTPPasswordMgr",
- "HTTPPasswordMgrWithDefaultRealm",
- "AbstractBasicAuthHandler",
- "HTTPBasicAuthHandler", "ProxyBasicAuthHandler",
- "AbstractDigestAuthHandler",
- "HTTPDigestAuthHandler", "ProxyDigestAuthHandler",
- "HTTPHandler", "HTTPSHandler", "FileHandler",
- "FTPHandler", "CacheFTPHandler",
- "UnknownHandler"]),
- ("urllib.error",
- ["URLError", "HTTPError"]),
- ]
- }
- # Duplicate the url parsing functions for urllib2.
- MAPPING["urllib2"].append(MAPPING["urllib"][1])
- def build_pattern():
- bare = set()
- for old_module, changes in MAPPING.items():
- for change in changes:
- new_module, members = change
- members = alternates(members)
- yield """import_name< 'import' (module=%r
- | dotted_as_names< any* module=%r any* >) >
- """ % (old_module, old_module)
- yield """import_from< 'from' mod_member=%r 'import'
- ( member=%s | import_as_name< member=%s 'as' any > |
- import_as_names< members=any* >) >
- """ % (old_module, members, members)
- yield """import_from< 'from' module_star=%r 'import' star='*' >
- """ % old_module
- yield """import_name< 'import'
- dotted_as_name< module_as=%r 'as' any > >
- """ % old_module
- # bare_with_attr has a special significance for FixImports.match().
- yield """power< bare_with_attr=%r trailer< '.' member=%s > any* >
- """ % (old_module, members)
- class FixUrllib(FixImports):
- def build_pattern(self):
- return "|".join(build_pattern())
- def transform_import(self, node, results):
- """Transform for the basic import case. Replaces the old
- import name with a comma separated list of its
- replacements.
- """
- import_mod = results.get("module")
- pref = import_mod.prefix
- names = []
- # create a Node list of the replacement modules
- for name in MAPPING[import_mod.value][:-1]:
- names.extend([Name(name[0], prefix=pref), Comma()])
- names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref))
- import_mod.replace(names)
- def transform_member(self, node, results):
- """Transform for imports of specific module elements. Replaces
- the module to be imported from with the appropriate new
- module.
- """
- mod_member = results.get("mod_member")
- pref = mod_member.prefix
- member = results.get("member")
- # Simple case with only a single member being imported
- if member:
- # this may be a list of length one, or just a node
- if isinstance(member, list):
- member = member[0]
- new_name = None
- for change in MAPPING[mod_member.value]:
- if member.value in change[1]:
- new_name = change[0]
- break
- if new_name:
- mod_member.replace(Name(new_name, prefix=pref))
- else:
- self.cannot_convert(node, "This is an invalid module element")
- # Multiple members being imported
- else:
- # a dictionary for replacements, order matters
- modules = []
- mod_dict = {}
- members = results["members"]
- for member in members:
- # we only care about the actual members
- if member.type == syms.import_as_name:
- as_name = member.children[2].value
- member_name = member.children[0].value
- else:
- member_name = member.value
- as_name = None
- if member_name != ",":
- for change in MAPPING[mod_member.value]:
- if member_name in change[1]:
- if change[0] not in mod_dict:
- modules.append(change[0])
- mod_dict.setdefault(change[0], []).append(member)
- new_nodes = []
- indentation = find_indentation(node)
- first = True
- def handle_name(name, prefix):
- if name.type == syms.import_as_name:
- kids = [Name(name.children[0].value, prefix=prefix),
- name.children[1].clone(),
- name.children[2].clone()]
- return [Node(syms.import_as_name, kids)]
- return [Name(name.value, prefix=prefix)]
- for module in modules:
- elts = mod_dict[module]
- names = []
- for elt in elts[:-1]:
- names.extend(handle_name(elt, pref))
- names.append(Comma())
- names.extend(handle_name(elts[-1], pref))
- new = FromImport(module, names)
- if not first or node.parent.prefix.endswith(indentation):
- new.prefix = indentation
- new_nodes.append(new)
- first = False
- if new_nodes:
- nodes = []
- for new_node in new_nodes[:-1]:
- nodes.extend([new_node, Newline()])
- nodes.append(new_nodes[-1])
- node.replace(nodes)
- else:
- self.cannot_convert(node, "All module elements are invalid")
- def transform_dot(self, node, results):
- """Transform for calls to module members in code."""
- module_dot = results.get("bare_with_attr")
- member = results.get("member")
- new_name = None
- if isinstance(member, list):
- member = member[0]
- for change in MAPPING[module_dot.value]:
- if member.value in change[1]:
- new_name = change[0]
- break
- if new_name:
- module_dot.replace(Name(new_name,
- prefix=module_dot.prefix))
- else:
- self.cannot_convert(node, "This is an invalid module element")
- def transform(self, node, results):
- if results.get("module"):
- self.transform_import(node, results)
- elif results.get("mod_member"):
- self.transform_member(node, results)
- elif results.get("bare_with_attr"):
- self.transform_dot(node, results)
- # Renaming and star imports are not supported for these modules.
- elif results.get("module_star"):
- self.cannot_convert(node, "Cannot handle star imports.")
- elif results.get("module_as"):
- self.cannot_convert(node, "This module is now multiple modules")
|