diff options
| author | Chris McDonough <chrism@plope.com> | 2010-10-25 10:34:49 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2010-10-25 10:34:49 -0400 |
| commit | 68a7110cda84e74f828f51d199f2e6872ba17f21 (patch) | |
| tree | 8cf0284c413353f73550c981c559b316709195b2 | |
| parent | 30d55eb56a6171e03febceff65145a5c0c6aa3d3 (diff) | |
| download | pyramid-68a7110cda84e74f828f51d199f2e6872ba17f21.tar.gz pyramid-68a7110cda84e74f828f51d199f2e6872ba17f21.tar.bz2 pyramid-68a7110cda84e74f828f51d199f2e6872ba17f21.zip | |
add 2to3 fixer script for repoze.bfg imports
| -rw-r--r-- | pyramid/fixers/__init__.py | 1 | ||||
| -rw-r--r-- | pyramid/fixers/fix_bfg_imports.py | 178 | ||||
| -rw-r--r-- | setup.py | 2 |
3 files changed, 181 insertions, 0 deletions
diff --git a/pyramid/fixers/__init__.py b/pyramid/fixers/__init__.py new file mode 100644 index 000000000..5bb534f79 --- /dev/null +++ b/pyramid/fixers/__init__.py @@ -0,0 +1 @@ +# package diff --git a/pyramid/fixers/fix_bfg_imports.py b/pyramid/fixers/fix_bfg_imports.py new file mode 100644 index 000000000..e93181be4 --- /dev/null +++ b/pyramid/fixers/fix_bfg_imports.py @@ -0,0 +1,178 @@ +import sys + +from lib2to3.refactor import get_fixers_from_package +from lib2to3.refactor import RefactoringTool +from lib2to3.fixer_util import Name +from lib2to3.fixer_util import attr_chain +from lib2to3 import fixer_base + +MAPPING = {'repoze.bfg':'pyramid'} + +for name in ( + 'compat', + 'configuration', + 'authentication', + 'authorization', + 'chameleon_text', + 'chameleon_zpt', + 'decorator', + 'encode', + 'events', + 'exceptions', + 'i18n', + 'includes', + 'interfaces', + 'location', + 'log', + 'paster', + 'path', + 'registry', + 'renderers', + 'request', + 'resource', + 'router', + 'scripting', + 'security', + 'settings', + 'static', + 'testing', + 'tests', + 'tests.test_configuration', + 'tests.ccbugapp', + 'tests.exceptionviewapp', + 'repoze.bfg.tests.exceptionviewapp.models', + 'tests.fixtureapp', + 'tests.fixtureapp.models', + 'tests.grokkedapp', + 'tests.hybridapp', + 'tests.localeapp', + 'tests.restbugapp', + 'tests.routesapp', + 'threadlocal', + 'traversal', + 'urldispatch', + 'url', + 'view', + 'wsgi', + 'zcml', + ): + frm = 'repoze.bfg.' + name + to = 'pyramid.' + name + MAPPING[frm] = to + +def alternates(members): + return "(" + "|".join(map(str, members)) + ")" + +def build_pattern(mapping=MAPPING): + mod_list = [] + + for key in mapping: + splitted = key.split('.') + joined = " '.' ".join(["'%s'" %s for s in splitted]) + mod_list.append(joined) + + mod_list = ' | '.join( + ['module_name=dotted_name< %s >' %s for s in mod_list]) + + yield """name_import=import_name< 'import' ((%s) | + multiple_imports=dotted_as_names< any* (%s) any* >) > + """ % (mod_list, mod_list) + yield """import_from< 'from' (%s) 'import' ['('] + ( any | import_as_name< any 'as' any > | + import_as_names< any* >) [')'] > + """ % mod_list + yield """import_name< 'import' (dotted_as_name< (%s) 'as' any > | + multiple_imports=dotted_as_names< + any* dotted_as_name< (%s) 'as' any > any* >) > + """ % (mod_list, mod_list) + + # Find usages of module members in code e.g. ``repoze.bfg`` or + # ``repoze.bfg.configuration`` + # 'repoze' trailer< '.' 'bfg' > trailer< '.' 'configuration' > + bare_names = [] + for key in mapping: + splitted = key.split('.') + tmp = ["'%s'" % splitted[0]] + for thing in splitted[1:]: + tmp.append(" trailer< '.' '%s' > " % thing) + bare_name = ''.join(tmp) + bare_names.append(bare_name) + + names = alternates(bare_names) + yield "power< bare_with_attr=%s >" % names + +class FixBfgImports(fixer_base.BaseFix): + + mapping = MAPPING + run_order = 8 + + def build_pattern(self): + pattern = "|".join(build_pattern(self.mapping)) + return pattern + + def compile_pattern(self): + # We override this, so MAPPING can be pragmatically altered and the + # changes will be reflected in PATTERN. + self.PATTERN = self.build_pattern() + super(FixBfgImports, self).compile_pattern() + + # Don't match the node if it's within another match. + def match(self, node): + match = super(FixBfgImports, self).match + results = match(node) + if results: + # Module usage could be in the trailer of an attribute lookup, so we + # might have nested matches when "bare_with_attr" is present. + if "bare_with_attr" not in results and \ + any(match(obj) for obj in attr_chain(node, "parent")): + return False + return results + return False + + def start_tree(self, tree, filename): + super(FixBfgImports, self).start_tree(tree, filename) + self.replace = {} + + def transform(self, node, results): + # Mostly copied from fix_imports.py + import_mod = results.get("module_name") + if import_mod: + try: + mod_name = import_mod.value + except AttributeError: + # XXX: A hack to remove whitespace prefixes and suffixes + mod_name = str(import_mod).strip() + new_name = self.mapping[mod_name] + import_mod.replace(Name(new_name, prefix=import_mod.prefix)) + if "name_import" in results: + # If it's not a "from x import x, y" or "import x as y" import, + # marked its usage to be replaced. + self.replace[mod_name] = new_name + if "multiple_imports" in results: + # This is a nasty hack to fix multiple imports on a line (e.g., + # "import StringIO, urlparse"). The problem is that I can't + # figure out an easy way to make a pattern recognize the keys of + # MAPPING randomly sprinkled in an import statement. + results = self.match(node) + if results: + self.transform(node, results) + else: + # Replace usage of the module. + bare_name_text = ''.join(map(str,results['bare_with_attr'])).strip() + new_name = self.replace.get(bare_name_text) + bare_name = results["bare_with_attr"][0] + + if new_name: + node.replace(Name(new_name, prefix=bare_name.prefix)) + +def main(argv=None): + if argv is None: + argv = sys.argv + path = argv[1] + fixer_names = get_fixers_from_package('repoze.bfg.fixers') + tool = RefactoringTool(fixer_names) + tool.refactor([path], write=True) + +if __name__ == '__main__': + main() + @@ -83,6 +83,8 @@ setup(name='pyramid', pyramid_alchemy=pyramid.paster:AlchemyProjectTemplate [paste.paster_command] pyramid_shell=pyramid.paster:BFGShellCommand + [console_scripts] + bfg2pyramid = pyramid.fixers.fix_bfg_imports:main """ ) |
