Fissix
Fissix is a Python library that monkeypatches and overrides the default behavior of the standard library `lib2to3`. It provides an enhanced and actively maintained version of `lib2to3`, primarily used for transforming Python code, especially for backporting `2to3` fixes for Python 3 codebases. It aims to be a drop-in replacement for `lib2to3`'s code transformation utilities. The current version is 24.4.24, and it often sees updates in conjunction with CPython development.
Common errors
-
AttributeError: module 'lib2to3.fixes' has no attribute 'fix_xxx'
cause You are attempting to access a fixer or utility module that is either specific to `fissix` or has been overridden by `fissix`, but you are trying to import it directly from the original `lib2to3.fixes` namespace.fixWhile `fissix` monkeypatches `lib2to3`, it's best to explicitly import fixers and utilities from `fissix` modules (e.g., `from fissix.fixes import fix_print` or `from fissix.fixer_util import Name`). If using `RefactoringTool`, pass the fully-qualified string name like `'fissix.fixes.fix_print'`. -
RuntimeWarning: This application uses the lib2to3 module, which is deprecated in Python 3.x and scheduled for removal in Python 3.12.
cause `fissix` is built on and extends `lib2to3`. Even when using `fissix`, the underlying (and now deprecated) standard library `lib2to3` module is still utilized, triggering Python's deprecation warning.fixThis warning is expected and generally harmless when using `fissix`, as `fissix` aims to maintain and enhance `lib2to3`. It indicates Python's stance on the *standard library* `lib2to3`, not a problem with `fissix` itself. You can choose to suppress `DeprecationWarning` if it becomes too noisy, but it's important to understand its origin. -
SystemExit: 2 (or other non-zero exit code) when calling fissix.main.main()
cause `fissix.main.main()` is designed to mimic command-line execution and calls `sys.exit()` upon completion, including when an error occurs or invalid arguments are passed.fixIf you need to call `fissix.main.main()` programmatically, wrap the call in a `try...except SystemExit` block to prevent your script from exiting. For purely programmatic code transformations without command-line behavior, it's generally better to use `fissix.refactor.RefactoringTool` directly.
Warnings
- breaking Fissix monkeypatches the standard library `lib2to3` module upon import. This can lead to unexpected behavior or conflicts if other libraries also attempt to modify `lib2to3` or rely on its exact default implementation before `fissix` is imported.
- gotcha `fissix` is a fork and enhancement of `lib2to3`. While it aims for full compatibility and improvement, subtle differences in behavior, available fixers, or parsing logic might exist compared to the vanilla `lib2to3` module. Always test thoroughly when migrating or expecting precise `lib2to3` parity.
- gotcha `fissix` is primarily designed for transforming Python 3 code or modernizing code that was originally Python 2 but intended for Python 3 environments. It is not a tool to run *on* a Python 2 interpreter to convert Python 2 source code to Python 3.
Install
-
pip install fissix
Imports
- RefactoringTool
from fissix.refactor import RefactoringTool
- main
import fissix.main
Quickstart
import io
from fissix.refactor import RefactoringTool, get_all_fix_names
# Get all available fixers provided by fissix
all_fixer_names = get_all_fix_names()
# Create a RefactoringTool instance with the desired fixers.
# By default, get_all_fix_names() includes standard 2to3 fixes and fissix enhancements.
tool = RefactoringTool(all_fixer_names)
# Source code to transform
original_code = """
print "Hello, world!"
if True:
pass # A comment
"""
# Apply the transformation to the string.
# refactor_string returns a Node object representing the transformed code tree.
transformed_tree = tool.refactor_string(original_code, "<string>")
# Convert the transformed tree back to a string representation
transformed_code = str(transformed_tree)
print("Original code:\n" + original_code)
print("\nTransformed code:\n" + transformed_code)