Index: lib2to3/tests/test_fixers.py =================================================================== --- lib2to3/tests/test_fixers.py (revision 65981) +++ lib2to3/tests/test_fixers.py (working copy) @@ -3435,7 +3435,95 @@ s = """[i for i in m]""" self.unchanged(s) +class Test_exitfunc(FixerTestCase): + fixer = "exitfunc" + + def test_1(self): + b = """ + import sys + sys.exitfunc = my_atexit + """ + a = """ + import sys + import atexit + atexit.register(my_atexit) + """ + self.check(b, a) + + def test_2(self): + b = """ + import sys, crumbs + sys.exitfunc = my_func + """ + a = """ + import sys, crumbs, atexit + atexit.register(my_func) + """ + self.check(b, a) + + def test_3(self): + b = """ + import sys + sys.exitfunc = do(d)/a()+complex(f=23, g=23)*expression + """ + a = """ + import sys + import atexit + atexit.register(do(d)/a()+complex(f=23, g=23)*expression) + """ + self.check(b, a) + + def test_4(self): + b = """ + import sys # Foo + sys.exitfunc = f # Blah + """ + a = """ + import sys + import atexit # Foo + atexit.register(f) # Blah + """ + self.check(b, a) + + def test_5(self): + b = """ + import apples, sys, crumbs, larry # Pleasant comments + sys.exitfunc = func + """ + a = """ + import apples, sys, crumbs, larry, atexit # Pleasant comments + atexit.register(func) + """ + self.check(b, a) + + def test_6(self): + b = """ + import sys + def f(): + sys.exitfunc = func + """ + a = """ + import sys + import atexit + def f(): + atexit.register(func) + """ + self.check(b, a) + + def test_warning(self): + b = """sys.exitfunc = f""" + a = """atexit.register(f)""" + msg = "Can't find sys import; Please add an atexit import at the " \ + "top of your file." + self.warns(b, a, msg) + + + def test_unchanged(self): + s = """f(sys.exitfunc)""" + self.unchanged(s) + + if __name__ == "__main__": import __main__ support.run_all_tests(__main__) Index: lib2to3/fixes/fix_exitfunc.py =================================================================== --- lib2to3/fixes/fix_exitfunc.py (revision 0) +++ lib2to3/fixes/fix_exitfunc.py (revision 0) @@ -0,0 +1,68 @@ +""" +Convert use of sys.exitfunc to use the atexit module. +""" + +# Author: Benjamin Peterson + +from .. import pytree +from ..fixer_base import BaseFix +from ..fixer_util import Name, Attr, Call, Comma, Newline, syms + + +class FixExitfunc(BaseFix): + + PATTERN = """ + ( + sys_import=import_name<'import' + ('sys' + | + dotted_as_names< (any ',')* 'sys' (',' any)* > + ) + > + | + expr_stmt< + power< 'sys' trailer< '.' 'exitfunc' > > + '=' func=any > + ) + """ + + def __init__(self, *args): + super(FixExitfunc, self).__init__(*args) + self.sys_import = None + + def transform(self, node, results): + # First, find a the sys import (we'll just hope it's global scope) + if "sys_import" in results: + if self.sys_import is None: + self.sys_import = results["sys_import"] + return + + func = results["func"].clone() + func.set_prefix("") + register = pytree.Node(syms.power, + Attr(Name("atexit"), Name("register")) + ) + call = Call(register, [func], node.get_prefix()) + node.replace(call) + + if self.sys_import is None: + # That's interesting + self.warning(node, "Can't find sys import; Please add an atexit " \ + "import at the top of your file.") + return + + # Now we add a atexit import after the sys import + if self.sys_import.children[1].type == syms.dotted_as_names: + kids = self.sys_import.children[1].children + kids.append(Comma()) + kids.append(Name("atexit", " ")) + else: + containing_stmt = self.sys_import.parent + position = containing_stmt.children.index(self.sys_import) + stmt_container = containing_stmt.parent + new_import = pytree.Node("import_name", + [Name("import"), Name("atexit", " ")] + ) + new = pytree.Node("simple_stmt", [new_import]) + containing_stmt.children.insert(position + 1, Newline()) + containing_stmt.children.insert(position + 2, new) Property changes on: lib2to3/fixes/fix_exitfunc.py ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + native