Skip to content

bpo-39313: Add an option to RefactoringTool for using exec as a function #17967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Doc/library/2to3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ presence of the ``from __future__ import print_function`` compiler directive, it
modifies its internal grammar to interpret :func:`print` as a function. This
change can also be enabled manually with the :option:`!-p` flag. Use
:option:`!-p` to run fixers on code that already has had its print statements
converted.
converted. Also :option:`!-e` can be used to make :func:`exec` a function.

The :option:`!-o` or :option:`!--output-dir` option allows specification of an
alternate directory for processed output files to be written to. The
Expand Down
5 changes: 5 additions & 0 deletions Lib/lib2to3/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ def main(fixer_pkg, args=None):
help="List available transformations")
parser.add_option("-p", "--print-function", action="store_true",
help="Modify the grammar so that print() is a function")
parser.add_option("-e", "--exec-function", action="store_true",
help="Modify the grammar so that exec() is a function")
parser.add_option("-v", "--verbose", action="store_true",
help="More verbose logging")
parser.add_option("--no-diffs", action="store_true",
Expand Down Expand Up @@ -211,6 +213,9 @@ def main(fixer_pkg, args=None):
if options.print_function:
flags["print_function"] = True

if options.exec_function:
flags["exec_function"] = True

# Set up logging handler
level = logging.DEBUG if options.verbose else logging.INFO
logging.basicConfig(format='%(name)s: %(message)s', level=level)
Expand Down
12 changes: 8 additions & 4 deletions Lib/lib2to3/refactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class FixerError(Exception):
class RefactoringTool(object):

_default_options = {"print_function" : False,
"exec_function": False,
"write_unchanged_files" : False}

CLASS_PREFIX = "Fix" # The prefix for fixer classes
Expand All @@ -173,10 +174,13 @@ def __init__(self, fixer_names, options=None, explicit=None):
self.options = self._default_options.copy()
if options is not None:
self.options.update(options)
if self.options["print_function"]:
self.grammar = pygram.python_grammar_no_print_statement
else:
self.grammar = pygram.python_grammar
self.grammar = pygram.python_grammar.copy()

if self.options['print_function']:
del self.grammar.keywords["print"]
elif self.options['exec_function']:
del self.grammar.keywords["exec"]

# When this is True, the refactor*() methods will call write_file() for
# files processed even if they were not changed during refactoring. If
# and only if the refactor method's write parameter was True.
Expand Down
10 changes: 7 additions & 3 deletions Lib/lib2to3/tests/test_refactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ def rt(self, options=None, fixers=_DEFAULT_FIXERS, explicit=None):

def test_print_function_option(self):
rt = self.rt({"print_function" : True})
self.assertIs(rt.grammar, pygram.python_grammar_no_print_statement)
self.assertIs(rt.driver.grammar,
pygram.python_grammar_no_print_statement)
self.assertNotIn("print", rt.grammar.keywords)
self.assertNotIn("print", rt.driver.grammar.keywords)

def test_exec_function_option(self):
rt = self.rt({"exec_function" : True})
self.assertNotIn("exec", rt.grammar.keywords)
self.assertNotIn("exec", rt.driver.grammar.keywords)

def test_write_unchanged_files_option(self):
rt = self.rt()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add a new ``exec_function`` option (*--exec-function* in the CLI) to
``RefactoringTool`` for making ``exec`` a function. Patch by Batuhan Taskaya.