Have you ever wished there was an automated refactoring tool?
While working on a Python code base, I was refactoring a considerable amount of Python from using named tuples to using Enums instead.
As an example, I was refactoring code from this:
Of course imagine having to do this refactor for more complex cases spread throughout an entire codebase.
Some time ago I watched a python conference about a tool called Redbaron that helps refactor your Python code. Unfortunately, judging by it’s Github repo, Redbaron’s last commit was 2 years ago, so I decided to keep looking for actively maintained tools.
Surprisingly, there is no specific go-to tool for this use case. So I surveyed what tools are available and provided my recommendations of what to use so you don’t have to do it yourself!
Here’s a list of the tools I encountered that aim to help you refactor Python code:
- Redbaron: Claims that “it will only modify your code where you ask him to” and achieves that by employing a Lossless AST. I didn’t check whether the claim is real or not, but I found the examples and documentation pretty difficult to follow.
- Baron: The predecessor of Redbaron, it appears to not be maintained anymore.
- Astor: Similar to Baron and Redbaron. It has had some commits lately but the documentation doesn’t have good examples and I found it difficult to even start using it.
- Rope: It also doesn’t have the greatest documentation, but it is easier to work with and also designed to be integrated with IDE’s.
- Bowler: This one is a project from Facebook Incubator. It has nice documentation and it’s easy to use. I recommend you check it out and give it a try.
As it happens, before finishing my research, I manually completed all the refactoring I had to do. But I still wanted to see what tool would be the best and to keep an eye on the future and see how the project evolves. I tested the two most promising projects from the list: Rope and Bowler. Those were the only ones that had proper support for Python projects in the sense that you could give them a path and would analyze the entire tree to look for Python code.
Let’s see an example implementation for Rope
To begin I wrote a Status implementation, which expresses an “active status” and “inactive status”, using two styles: an namedtuple approach and an Enum approach.
Commented code for producing refactoring
That does the trick but it feels too much like something that you could do with some regular expressions. It really does not give you the sense of refactoring or restructuring any more than just replacing some text.
Bowler implementation feels much cleaner
Bowler has a way of performing refactoring that looks like it is on the right track. It works like a pipeline and has a syntax similar to a SQL language. You perform a Query, then you can Filter matches to narrow the universe of possibilities, finally you perform changes or Modify the code. The tool has an interactive prompt that shows you a diff allowing you to confirm whether to write the changes or not.
To execute the script you can use the bowler cli tool or just use Python.
I recommend that you give Bowler a try and see what you can come up with.
In the future if I have to do some big refactoring I would try to start by writing a script with Bowler to save time and effort. I would love to see where the project goes if it keeps being maintained and improved. I think that it has a long way to go before it is mature.
I hope you find any of these tools useful and they serve you well on your next adventure!