annotate contrib/hgfixes/fix_leftover_imports.py @ 14966:0588fb0e2e8d

patch: use safehasattr instead of hasattr
author Augie Fackler <durin42@gmail.com>
date Mon, 25 Jul 2011 16:02:27 -0500
parents 626fe5c99231
children 9de689d20230
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
11949
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
1 "Fixer that translates some APIs ignored by the default 2to3 fixers."
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
2
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
3 # FIXME: This fixer has some ugly hacks. Its main design is based on that of
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
4 # fix_imports, from lib2to3. Unfortunately, the fix_imports framework only
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
5 # changes module names "without dots", meaning it won't work for some changes
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
6 # in the email module/package. Thus this fixer was born. I believe that with a
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
7 # bit more thinking, a more generic fixer can be implemented, but I'll leave
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
8 # that as future work.
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
9
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
10 from lib2to3.fixer_util import Name
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
11 from lib2to3.fixes import fix_imports
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
12
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
13 # This maps the old names to the new names. Note that a drawback of the current
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
14 # design is that the dictionary keys MUST have EXACTLY one dot (.) in them,
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
15 # otherwise things will break. (If you don't need a module hierarchy, you're
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
16 # better of just inherit from fix_imports and overriding the MAPPING dict.)
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
17
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
18 MAPPING = {'email.Utils': 'email.utils',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
19 'email.Errors': 'email.errors',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
20 'email.Header': 'email.header',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
21 'email.Parser': 'email.parser',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
22 'email.Encoders': 'email.encoders',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
23 'email.MIMEText': 'email.mime.text',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
24 'email.MIMEBase': 'email.mime.base',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
25 'email.Generator': 'email.generator',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
26 'email.MIMEMultipart': 'email.mime.multipart',
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
27 }
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
28
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
29 def alternates(members):
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
30 return "(" + "|".join(map(repr, members)) + ")"
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
31
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
32 def build_pattern(mapping=MAPPING):
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
33 packages = {}
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
34 for key in mapping:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
35 # What we are doing here is the following: with dotted names, we'll
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
36 # have something like package_name <trailer '.' module>. Then, we are
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
37 # making a dictionary to copy this structure. For example, if
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
38 # mapping={'A.B': 'a.b', 'A.C': 'a.c'}, it will generate the dictionary
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
39 # {'A': ['b', 'c']} to, then, generate something like "A <trailer '.'
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
40 # ('b' | 'c')".
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
41 name = key.split('.')
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
42 prefix = name[0]
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
43 if prefix in packages:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
44 packages[prefix].append(name[1:][0])
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
45 else:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
46 packages[prefix] = name[1:]
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
47
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
48 mod_list = ' | '.join(["'%s' '.' ('%s')" %
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
49 (key, "' | '".join(packages[key])) for key in packages])
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
50 mod_list = '(' + mod_list + ' )'
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
51 bare_names = alternates(mapping.keys())
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
52
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
53 yield """name_import=import_name< 'import' module_name=dotted_name< %s > >
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
54 """ % mod_list
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
55
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
56 yield """name_import=import_name< 'import'
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
57 multiple_imports=dotted_as_names< any*
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
58 module_name=dotted_name< %s >
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
59 any* >
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
60 >""" % mod_list
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
61
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
62 packs = ' | '.join(["'%s' trailer<'.' ('%s')>" % (key,
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
63 "' | '".join(packages[key])) for key in packages])
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
64
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
65 yield "power< package=(%s) trailer<'.' any > any* >" % packs
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
66
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
67 class FixLeftoverImports(fix_imports.FixImports):
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
68 # We want to run this fixer after fix_import has run (this shouldn't matter
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
69 # for hg, though, as setup3k prefers to run the default fixers first)
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
70 mapping = MAPPING
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
71
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
72 def build_pattern(self):
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
73 return "|".join(build_pattern(self.mapping))
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
74
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
75 def transform(self, node, results):
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
76 # Mostly copied from fix_imports.py
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
77 import_mod = results.get("module_name")
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
78 if import_mod:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
79 try:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
80 mod_name = import_mod.value
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
81 except AttributeError:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
82 # XXX: A hack to remove whitespace prefixes and suffixes
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
83 mod_name = str(import_mod).strip()
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
84 new_name = self.mapping[mod_name]
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
85 import_mod.replace(Name(new_name, prefix=import_mod.prefix))
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
86 if "name_import" in results:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
87 # If it's not a "from x import x, y" or "import x as y" import,
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
88 # marked its usage to be replaced.
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
89 self.replace[mod_name] = new_name
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
90 if "multiple_imports" in results:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
91 # This is a nasty hack to fix multiple imports on a line (e.g.,
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
92 # "import StringIO, urlparse"). The problem is that I can't
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
93 # figure out an easy way to make a pattern recognize the keys of
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
94 # MAPPING randomly sprinkled in an import statement.
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
95 results = self.match(node)
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
96 if results:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
97 self.transform(node, results)
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
98 else:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
99 # Replace usage of the module.
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
100 # Now this is, mostly, a hack
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
101 bare_name = results["package"][0]
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
102 bare_name_text = ''.join(map(str, results['package'])).strip()
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
103 new_name = self.replace.get(bare_name_text)
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
104 prefix = results['package'][0].prefix
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
105 if new_name:
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
106 bare_name.replace(Name(new_name, prefix=prefix))
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
107 results["package"][1].replace(Name(''))
626fe5c99231 hgfixes: added a fixer to convert changes in the email package
Renato Cunha <renatoc@gmail.com>
parents:
diff changeset
108