Author here: I created Bowler as a "hackamonth" project when I joined Facebook's internal Python Foundation team. We've already used it for a bunch of random codemods that touch a large number of source files throughout our codebase.<p>Happy to answer any questions you might have!
This was first presented at PyconAU 2018 - <a href="https://www.youtube.com/watch?v=9USGh4Uy-xQ" rel="nofollow">https://www.youtube.com/watch?v=9USGh4Uy-xQ</a>
This is akin to the other "codemod" facilities Facebook already uses for large-scale refactoring in <i>busy</i> codebases (particularly, their JS codebases), but for Python (<a href="https://github.com/facebook/codemod" rel="nofollow">https://github.com/facebook/codemod</a>, <a href="https://github.com/facebook/jscodeshift" rel="nofollow">https://github.com/facebook/jscodeshift</a>).
I could imagine a library of transformers being created using this tool.<p>For instance we’ve just enabled the pep3101 Flake8 plugin which enforces newstyle string formatting over % formatting. I’d love to see a transformer that automates that refactoring.
Is this to help migration from python 2 to python 3, or a tool to make python 3 better? it's unclear after I read it except it mentions it's based on 2to3.
How well does this handle dynamic constructs? Eg if I rename a method and elsewhere have<p><pre><code> if hasattr(obj, ‘foo’):
</code></pre>
does that get caught or not?
I haven't had to use it before, but another tool in that space is "undebt" from Yelp:<p><a href="https://github.com/Yelp/undebt" rel="nofollow">https://github.com/Yelp/undebt</a>