Skip to main content

Refex - refactoring expressions

Refex is a syntactically aware search-and-replace tool for Python, which allows you to specify code searches and rewrites using templates, or a more complex Clang-LibASTMatcher-like matcher interface.

Examples

Automatic parenthesis insertion: Refex will automatically insert parentheses to preserve the intended code structure:

$ echo "a = b.foo() * c" > test.py
$ refex --mode=py.expr '$x.foo()' --sub='$x.foo() + 1' -i test.py
...
$ cat test.py
a = (b.foo() + 1) * c

A naive regular expression replacement would have resulted in b.foo() + 1 * c, which is not equivalent, and is unrelated to the intended replacement.

Paired parentheses: Refex is aware of the full syntax tree, and will always match parentheses correctly:

$ echo "print(foo(bar(b))" > test.py
$ refex --mode=py.expr 'foo($x)' --sub='foo($x + 1)' -i test.py
...
$ cat test.py
a = print(foo(bar(b) + 1))

Here, a naive replacement using regular expressions could have resulted in either print(foo(bar(b)) + 1) or print(foo(bar(b) + 1)), depending on whether $x was matched greedily or non-greedily.

Combining replacements: you can pass multiple search/replace pairs to Refex which combine to do more complex rewrites. For example:

# Rewrites "self.assertTrue(x == False)" to "self.assertFalse(x)", even though
# that was not explicitly called out.
refex --mode=py.expr -i --iterate \
  --match='self.assertTrue($x == $y)'  --sub='self.assertEqual($x, $y)' \
  --match='self.assertEqual($x, False)' --sub='self.assertFalse($x)' \
  -R dir/

TODO: also describe --mode=py.

Getting started

Installation

TODO: Installation instructions will go here as soon as this gets up on PyPI, hang tight!

Current status

NOTE: Right now, the project is in the process of initial upload to github, PyPI, etc., so please don't publicize it widely. The initial release will be a 0.1 release.

Stable:

The APIs documented at https://refex.readthedocs.io/ are expected to remain mostly the same, except for trivial renames and moves.

These command-line interfaces are expected to remain roughly the same, without backwards-incompatible changes:

  • --mode=py.expr
  • --mode=fix
  • --mode=re

Unstable

  • All undocumented APIs (especially the API for creating a new matcher).
  • --mode=py.stmt is missing many safety and convenience features.
  • --mode=py, the matcher interface, will eventually need some fairly large restructuring to make it O(n), although simple uses should be unaffected.

(Also, all the stable parts are unstable too. This isn't a promise, just an expectation/statement of intent.)

Contributing

See the contribution guide

See Also

  • asttokens: the token-preserving AST library that Refex is built on top of.
  • Pasta: a code rewriting tool using AST mutation instead of string templates.
  • Semgrep: cross-language AST search using a similar approach.
  • lib2to3: the standard library's code rewriting tool based on the concrete syntax tree.

Disclaimer

You may have noticed Google copyright notices. This is not an officially supported Google product.

Metadata

Release files for refex 0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for refex 0.1
File Size Uploaded
refex-0.1.tar.gz 123.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for refex 0.1
File Interpreter ABI Platform
refex-0.1-py3-none-any.whl Python 3 none any Details

Total release size: 285.3 kB

Release files / refex-0.1.tar.gz

Download URL refex-0.1.tar.gz
Size 123.3 kB
Tags Source
SHA-256 checksum
How to use checksums
03e7044019f05eeacf85913a1a4a06723449661542b990bcf51ef1de21f8cbf5
BLAKE2b-256 checksum
How to use checksums
d8cfe5f4a8b927d7a06308abe69836306e4cfad3fd3d007fe635320648998a9a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.0.10 CPython/2.7.18 Linux/5.6.14-2rodete5-amd64

Release files / refex-0.1-py3-none-any.whl

Download URL refex-0.1-py3-none-any.whl
Size 162.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
13f4b2e76b267d2a07bbfee89b24e6ab34ecb125f1c3681ad3096869108564d3
BLAKE2b-256 checksum
How to use checksums
166eb8f20fdfe2f85400a49e285b2f8e890e598bd7f7d79e180db7f061e1612d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.0.10 CPython/2.7.18 Linux/5.6.14-2rodete5-amd64

Release history Release notifications | RSS feed

0.1.1

2 release files

This release

0.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page