Refactor
Simple, hassle-free, dependency-free, AST based fragmental source code refactoring and transformation toolkit.
Why?
Our framework is primarily built on the principle of "simple but effective transformations". We focus on refactorings that target a small span of source code, and work our way out from it. What this enables for us is being able to operate directly on a single format for both analyses and transformations. This is what we shine at compared to other similar tools.
How?
Let's not get into too much details, but just to give a sneak peek we
can try to write a rule that would replace the identifier placeholder
with 42.
import ast
from refactor import Rule, Replace, run
# Each refactor transformer inherits from "refactor.Rule"
class FillPlaceholders(Rule):
# And each rule implements a "match()" method, which would
# receive every node in the tree in a breadth-first order.
def match(self, node: ast.AST) -> Replace:
# This is where things get interesting. Instead of just writing
# filters with if statements, you can use the following assert
# based approach (a contract of transformation).
# For this case, our contract is going to be: if the given node
# is an identifier with the name of "placeholder", it will be
# replaced with literal "42".
assert isinstance(node, ast.Name)
assert node.id == "placeholder"
# And this is where we choose what action we are taking for the
# given node (which we have verified with our contract). There
# are multiple transformation actions, but in this case what we
# need is something that replaces a node with another one.
replacement = ast.Constant(42)
return Replace(node, replacement)
if __name__ == "__main__":
# And finally in here, we just use the default CLI that comes
# bundled with refactor. When provided with a bunch of rules,
# it creates a simple interface that can process given files
# show the diff for changes and even apply them.
run(rules=[FillPlaceholders])
If we run the rule above on a file, we can see how it performs:
--- test_file.py
+++ test_file.py
@@ -1,11 +1,11 @@
def main():
- print(placeholder * 3 + 2)
+ print(42 * 3 + 2)
- print(2 + placeholder + 3)
+ print(2 + 42 + 3)
# some comments
- placeholder # maybe other comments
+ 42 # maybe other comments
if something:
other_thing
- print(placeholder)
+ print(42)
if __name__ == "__main__":
main()
For learning more, check our documentation out!
Release files for refactor 0.6.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| refactor-0.6.3.tar.gz | 25.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| refactor-0.6.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.4 kB
Release files / refactor-0.6.3.tar.gz
| Download URL | refactor-0.6.3.tar.gz |
|---|---|
| Size | 25.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
165f969522894ab4db7e14fe5408d7c664b0d36a208b76aa3d8e1898beb07d5f
|
|
BLAKE2b-256 checksum How to use checksums |
831d19247d5781c076a00932438a620a18bdc41d62a0783bf43deba9098828be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.1 CPython/3.9.15
|
Release files / refactor-0.6.3-py3-none-any.whl
| Download URL | refactor-0.6.3-py3-none-any.whl |
|---|---|
| Size | 29.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c9b8a1622c93727c81958aef43fe9293f6d61c27c1bc8742f69f460a8bf33622
|
|
BLAKE2b-256 checksum How to use checksums |
c5b73bed70c569f19161744b2d5e1768e33552af499bd863759453f49633efe4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.1 CPython/3.9.15
|