Index: lib2to3/tests/test_fixers.py =================================================================== --- lib2to3/tests/test_fixers.py (revision 67657) +++ lib2to3/tests/test_fixers.py (working copy) @@ -3227,6 +3227,52 @@ """ 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 + 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_3(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_unchanged(self): + s = """f(sys.exitfunc)""" + self.unchanged(s) + class Test_basestring(FixerTestCase): fixer = "basestring" Index: lib2to3/fixes/fix_exitfunc.py =================================================================== --- lib2to3/fixes/fix_exitfunc.py (revision 0) +++ lib2to3/fixes/fix_exitfunc.py (revision 0) @@ -0,0 +1,29 @@ +"""Fixed that Convers use of sys.exitfunc to use the atexit module. +""" +# Author: Armin Ronacher, Benjamin Peterson + +# Local imports +from .. import pytree, fixer_base +from ..fixer_util import Name, Attr, Call, does_tree_import, touch_import + + +class FixExitfunc(fixer_base.BaseFix): + + PATTERN = """ + expr_stmt< + power< 'sys' trailer< '.' 'exitfunc' > > + '=' func=any > + """ + + def transform(self, node, results): + # do nothing if sys is not imported + if not does_tree_import(None, "sys", node): + return + + touch_import(None, "atexit", node) + + func = results["func"].clone() + func.set_prefix("") + register = pytree.Node(self.syms.power, + Attr(Name("atexit"), Name("register"))) + node.replace(Call(register, [func], node.get_prefix()))