Add foundation for automatic refactoring tool - #53
Open
MWR27 wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This tool takes advantage of the warnings thrown in the Pygrate runtime. Built off of lib2to3, it refactors the Python 2 source code according to given warnings. The tool is a Python module called
pygrate2and is run as such:The tool runs
sourceand writes the refactored files into the directorydest.sourcecan either be a single.pyfile or a directory. Ifsourceis a directory, then the tool assumessourceis a module.After the execution(s) of
sourceis complete, the warnings are collected and passed to the interactive tool. For each warning, the tool will show the user the refactoring and prompt the user to apply or skip it. After processing every warning, it will apply the desired fixes. Here is an example:Technical Details
Expanding on lib2to3, the tool takes a set of fixers and applies them to the source code. As shown above, fixers are only applied to the actual warnings thrown. The tool is passed a dictionary that maps each warning to a fixer.
All dynamic fixers are located in
pygrate2/fixes/and extendSemanticFix, which is located inpygrate2/semfixer_base.py. The tool currently has one fixer calledFixSemDiv(infix_sem_div.py) to handle classic division. This fixer simply replaces any instance of integer division (provided by the warnings) with a helper function calledclassic_divthat preserves the behavior of Python 2 division. Helper functions are defined inpygrate2/pygrate_helpers.py. Any fixer inheritingSemanticFixcontains a class constant calledHELPER_FUNCTIONto store name of the helper function associated with the fixer, if there is one. When a fixer'stransformfunction is called, it must set its Boolean valueself.wrote_helperto indicate whether the helper function was included in the transformation. This is necessary for the tool to determine what helper functions should be written to the output. Ifsourceis a single file, the helper functions will be appended to the end of the file. Ifsourceis a directory,pygrate_helpers.pyis created at the top-level directory, containing the necessary functions, and import statements are inserted at the top of files that use helpers.To map a warning to a fixer, simply add an entry to
warning_fixersinpygrate2/main.py, where the key is the warning message and the value is the name of the fixer file without the extension. Currently, there is only one entry:Note that all fixer files must reside in
pygrate2/fixes/, and the file name must follow the lib2to3 convention, in snake case matching with the fixer class's Pascal case (e.g.FixSemDivandfix_sem_div.py).Since this tool depends on warnings in runtime, it is likely that a single run of
sourcedoes not catch every 2-to-3 incompatibility. There is an option--argv, which takes in a text file.sourceis run for each line in the file, and each line will be passed as the command-line arguments for the program. This makes it easier for test coverage if the program takes input.Current limitations