diff --git a/maint/scripts/custom_fixers/__init__.py b/maint/scripts/custom_fixers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/maint/scripts/custom_fixers/fix_future_imports.py b/maint/scripts/custom_fixers/fix_future_imports.py new file mode 100644 index 00000000..c371a554 --- /dev/null +++ b/maint/scripts/custom_fixers/fix_future_imports.py @@ -0,0 +1,59 @@ +"""Updates all source files to import the same set of __future__ directives. +""" +from lib2to3 import fixer_base +from lib2to3 import pytree +from lib2to3.pgen2 import token +from lib2to3.fixer_util import FromImport, Name, Comma, Newline + +# copied from fix_tuple_params.py +def is_docstring(stmt): + return isinstance(stmt, pytree.Node) and \ + stmt.children[0].type == token.STRING + +class FixFutureImports(fixer_base.BaseFix): + BM_compatible = True + + PATTERN = """import_from< 'from' module_name="__future__" 'import' any >""" + + def start_tree(self, tree, filename): + self.found_future_import = False + + def new_future_import(self, old): + new = FromImport("__future__", + [Name("absolute_import", prefix=" "), Comma(), + Name("with_statement", prefix=" ")]) + if old is not None: + new.prefix = old.prefix + return new + + def transform(self, node, results): + self.found_future_import = True + return self.new_future_import(node) + + def finish_tree(self, tree, filename): + if self.found_future_import: + return + if not isinstance(tree, pytree.Node): + # Empty files (usually __init__.py) show up as a single Leaf + # instead of a Node, so leave them alone + return + first_stmt = tree.children[0] + if is_docstring(first_stmt): + # Skip a line and add the import after the docstring + tree.insert_child(1, Newline()) + pos = 2 + elif first_stmt.prefix: + # No docstring, but an initial comment (perhaps a #! line). + # Transfer the initial comment to a new blank line. + newline = Newline() + newline.prefix = first_stmt.prefix + first_stmt.prefix = "" + tree.insert_child(0, newline) + pos = 1 + else: + # No comments or docstring, just insert at the start + pos = 0 + tree.insert_child(pos, self.new_future_import(None)) + tree.insert_child(pos+1, Newline()) # terminates the import stmt + + diff --git a/maint/scripts/run_fixers.py b/maint/scripts/run_fixers.py new file mode 100755 index 00000000..cfa2c36c --- /dev/null +++ b/maint/scripts/run_fixers.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +import sys +from lib2to3.main import main + +sys.exit(main("custom_fixers"))