fix_imports2.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. u"""
  2. Fixer for complicated imports
  3. """
  4. from lib2to3 import fixer_base
  5. from lib2to3.fixer_util import Name, String, FromImport, Newline, Comma
  6. from libfuturize.fixer_util import touch_import_top
  7. TK_BASE_NAMES = (u'ACTIVE', u'ALL', u'ANCHOR', u'ARC',u'BASELINE', u'BEVEL', u'BOTH',
  8. u'BOTTOM', u'BROWSE', u'BUTT', u'CASCADE', u'CENTER', u'CHAR',
  9. u'CHECKBUTTON', u'CHORD', u'COMMAND', u'CURRENT', u'DISABLED',
  10. u'DOTBOX', u'E', u'END', u'EW', u'EXCEPTION', u'EXTENDED', u'FALSE',
  11. u'FIRST', u'FLAT', u'GROOVE', u'HIDDEN', u'HORIZONTAL', u'INSERT',
  12. u'INSIDE', u'LAST', u'LEFT', u'MITER', u'MOVETO', u'MULTIPLE', u'N',
  13. u'NE', u'NO', u'NONE', u'NORMAL', u'NS', u'NSEW', u'NUMERIC', u'NW',
  14. u'OFF', u'ON', u'OUTSIDE', u'PAGES', u'PIESLICE', u'PROJECTING',
  15. u'RADIOBUTTON', u'RAISED', u'READABLE', u'RIDGE', u'RIGHT',
  16. u'ROUND', u'S', u'SCROLL', u'SE', u'SEL', u'SEL_FIRST', u'SEL_LAST',
  17. u'SEPARATOR', u'SINGLE', u'SOLID', u'SUNKEN', u'SW', u'StringTypes',
  18. u'TOP', u'TRUE', u'TclVersion', u'TkVersion', u'UNDERLINE',
  19. u'UNITS', u'VERTICAL', u'W', u'WORD', u'WRITABLE', u'X', u'Y', u'YES',
  20. u'wantobjects')
  21. PY2MODULES = {
  22. u'urllib2' : (
  23. u'AbstractBasicAuthHandler', u'AbstractDigestAuthHandler',
  24. u'AbstractHTTPHandler', u'BaseHandler', u'CacheFTPHandler',
  25. u'FTPHandler', u'FileHandler', u'HTTPBasicAuthHandler',
  26. u'HTTPCookieProcessor', u'HTTPDefaultErrorHandler',
  27. u'HTTPDigestAuthHandler', u'HTTPError', u'HTTPErrorProcessor',
  28. u'HTTPHandler', u'HTTPPasswordMgr',
  29. u'HTTPPasswordMgrWithDefaultRealm', u'HTTPRedirectHandler',
  30. u'HTTPSHandler', u'OpenerDirector', u'ProxyBasicAuthHandler',
  31. u'ProxyDigestAuthHandler', u'ProxyHandler', u'Request',
  32. u'StringIO', u'URLError', u'UnknownHandler', u'addinfourl',
  33. u'build_opener', u'install_opener', u'parse_http_list',
  34. u'parse_keqv_list', u'randombytes', u'request_host', u'urlopen'),
  35. u'urllib' : (
  36. u'ContentTooShortError', u'FancyURLopener',u'URLopener',
  37. u'basejoin', u'ftperrors', u'getproxies',
  38. u'getproxies_environment', u'localhost', u'pathname2url',
  39. u'quote', u'quote_plus', u'splitattr', u'splithost',
  40. u'splitnport', u'splitpasswd', u'splitport', u'splitquery',
  41. u'splittag', u'splittype', u'splituser', u'splitvalue',
  42. u'thishost', u'unquote', u'unquote_plus', u'unwrap',
  43. u'url2pathname', u'urlcleanup', u'urlencode', u'urlopen',
  44. u'urlretrieve',),
  45. u'urlparse' : (
  46. u'parse_qs', u'parse_qsl', u'urldefrag', u'urljoin',
  47. u'urlparse', u'urlsplit', u'urlunparse', u'urlunsplit'),
  48. u'dbm' : (
  49. u'ndbm', u'gnu', u'dumb'),
  50. u'anydbm' : (
  51. u'error', u'open'),
  52. u'whichdb' : (
  53. u'whichdb',),
  54. u'BaseHTTPServer' : (
  55. u'BaseHTTPRequestHandler', u'HTTPServer'),
  56. u'CGIHTTPServer' : (
  57. u'CGIHTTPRequestHandler',),
  58. u'SimpleHTTPServer' : (
  59. u'SimpleHTTPRequestHandler',),
  60. u'FileDialog' : TK_BASE_NAMES + (
  61. u'FileDialog', u'LoadFileDialog', u'SaveFileDialog',
  62. u'dialogstates', u'test'),
  63. u'tkFileDialog' : (
  64. u'Directory', u'Open', u'SaveAs', u'_Dialog', u'askdirectory',
  65. u'askopenfile', u'askopenfilename', u'askopenfilenames',
  66. u'askopenfiles', u'asksaveasfile', u'asksaveasfilename'),
  67. u'SimpleDialog' : TK_BASE_NAMES + (
  68. u'SimpleDialog',),
  69. u'tkSimpleDialog' : TK_BASE_NAMES + (
  70. u'askfloat', u'askinteger', u'askstring', u'Dialog'),
  71. u'SimpleXMLRPCServer' : (
  72. u'CGIXMLRPCRequestHandler', u'SimpleXMLRPCDispatcher',
  73. u'SimpleXMLRPCRequestHandler', u'SimpleXMLRPCServer',
  74. u'list_public_methods', u'remove_duplicates',
  75. u'resolve_dotted_attribute'),
  76. u'DocXMLRPCServer' : (
  77. u'DocCGIXMLRPCRequestHandler', u'DocXMLRPCRequestHandler',
  78. u'DocXMLRPCServer', u'ServerHTMLDoc',u'XMLRPCDocGenerator'),
  79. }
  80. MAPPING = { u'urllib.request' :
  81. (u'urllib2', u'urllib'),
  82. u'urllib.error' :
  83. (u'urllib2', u'urllib'),
  84. u'urllib.parse' :
  85. (u'urllib2', u'urllib', u'urlparse'),
  86. u'dbm.__init__' :
  87. (u'anydbm', u'whichdb'),
  88. u'http.server' :
  89. (u'CGIHTTPServer', u'SimpleHTTPServer', u'BaseHTTPServer'),
  90. u'tkinter.filedialog' :
  91. (u'tkFileDialog', u'FileDialog'),
  92. u'tkinter.simpledialog' :
  93. (u'tkSimpleDialog', u'SimpleDialog'),
  94. u'xmlrpc.server' :
  95. (u'DocXMLRPCServer', u'SimpleXMLRPCServer'),
  96. }
  97. # helps match 'http', as in 'from http.server import ...'
  98. simple_name = u"name='%s'"
  99. # helps match 'server', as in 'from http.server import ...'
  100. simple_attr = u"attr='%s'"
  101. # helps match 'HTTPServer', as in 'from http.server import HTTPServer'
  102. simple_using = u"using='%s'"
  103. # helps match 'urllib.request', as in 'import urllib.request'
  104. dotted_name = u"dotted_name=dotted_name< %s '.' %s >"
  105. # helps match 'http.server', as in 'http.server.HTTPServer(...)'
  106. power_twoname = u"pow=power< %s trailer< '.' %s > trailer< '.' using=any > any* >"
  107. # helps match 'dbm.whichdb', as in 'dbm.whichdb(...)'
  108. power_onename = u"pow=power< %s trailer< '.' using=any > any* >"
  109. # helps match 'from http.server import HTTPServer'
  110. # also helps match 'from http.server import HTTPServer, SimpleHTTPRequestHandler'
  111. # also helps match 'from http.server import *'
  112. from_import = u"from_import=import_from< 'from' %s 'import' (import_as_name< using=any 'as' renamed=any> | in_list=import_as_names< using=any* > | using='*' | using=NAME) >"
  113. # helps match 'import urllib.request'
  114. name_import = u"name_import=import_name< 'import' (%s | in_list=dotted_as_names< imp_list=any* >) >"
  115. #############
  116. # WON'T FIX #
  117. #############
  118. # helps match 'import urllib.request as name'
  119. name_import_rename = u"name_import_rename=dotted_as_name< %s 'as' renamed=any >"
  120. # helps match 'from http import server'
  121. from_import_rename = u"from_import_rename=import_from< 'from' %s 'import' (%s | import_as_name< %s 'as' renamed=any > | in_list=import_as_names< any* (%s | import_as_name< %s 'as' renamed=any >) any* >) >"
  122. def all_modules_subpattern():
  123. u"""
  124. Builds a pattern for all toplevel names
  125. (urllib, http, etc)
  126. """
  127. names_dot_attrs = [mod.split(u".") for mod in MAPPING]
  128. ret = u"( " + u" | ".join([dotted_name % (simple_name % (mod[0]),
  129. simple_attr % (mod[1])) for mod in names_dot_attrs])
  130. ret += u" | "
  131. ret += u" | ".join([simple_name % (mod[0]) for mod in names_dot_attrs if mod[1] == u"__init__"]) + u" )"
  132. return ret
  133. def build_import_pattern(mapping1, mapping2):
  134. u"""
  135. mapping1: A dict mapping py3k modules to all possible py2k replacements
  136. mapping2: A dict mapping py2k modules to the things they do
  137. This builds a HUGE pattern to match all ways that things can be imported
  138. """
  139. # py3k: urllib.request, py2k: ('urllib2', 'urllib')
  140. yield from_import % (all_modules_subpattern())
  141. for py3k, py2k in mapping1.items():
  142. name, attr = py3k.split(u'.')
  143. s_name = simple_name % (name)
  144. s_attr = simple_attr % (attr)
  145. d_name = dotted_name % (s_name, s_attr)
  146. yield name_import % (d_name)
  147. yield power_twoname % (s_name, s_attr)
  148. if attr == u'__init__':
  149. yield name_import % (s_name)
  150. yield power_onename % (s_name)
  151. yield name_import_rename % (d_name)
  152. yield from_import_rename % (s_name, s_attr, s_attr, s_attr, s_attr)
  153. class FixImports2(fixer_base.BaseFix):
  154. run_order = 4
  155. PATTERN = u" | \n".join(build_import_pattern(MAPPING, PY2MODULES))
  156. def transform(self, node, results):
  157. touch_import_top(u'future', u'standard_library', node)