Skip to content

Modifying Code

Once you've found code elements, you can transform them.

Class Operations

Renaming

cls = rj.find_classes("OldName").first()
result = cls.rename("NewName")

Adding Methods

cls = rj.file("models.py").find_class("User")

# Simple method
cls.add_method("validate", body="return True")

# With parameters and return type
# `params` lists the parameters after `self` (which is added automatically)
cls.add_method(
    "get_display_name",
    params="include_title: bool = False",
    return_type="str",
    body="return f'{self.first_name} {self.last_name}'"
)

# With decorator
cls.add_method(
    "cached_value",
    body="return self._compute()",
    decorators=["@cached_property"]
)

Adding Attributes

cls.add_attribute("created_at", type_hint="datetime", default="None")
cls.add_attribute("MAX_RETRIES", type_hint="int", default="3")

Adding Decorators

cls.add_decorator("dataclass")
cls.add_decorator("dataclass(frozen=True)")

Removing Decorators

cls.remove_decorator("dataclass")

Inheritance

cls.add_base_class("BaseModel")
cls.remove_base_class("OldBase")
cls.add_mixin("LoggingMixin")

Deleting

cls.delete()

Duplicating

cls.duplicate("UserCopy")

Method Operations

Renaming

method = cls.find_method("old_name")
method.rename("new_name")

Adding Decorators

method.add_decorator("staticmethod")
method.add_decorator("lru_cache(maxsize=100)")

Removing Decorators

method.remove_decorator("staticmethod")

Inserting Statements

# At the start of the method body
method.insert_statement("self.validate()", position="start")

# At the end of the method body
method.insert_statement("self.log_action()", position="end")

Parameters

# Add a parameter
method.add_parameter("timeout", type_annotation="int", default_value="30")

# Remove a parameter
method.remove_parameter("deprecated_arg")

# Rename a parameter
method.rename_parameter("old_name", "new_name")

Type Hints

method.set_return_type("list[str]")
method.set_parameter_type("data", "dict[str, Any]")
method.remove_type_hints()  # Strip all type annotations

Deleting

method.delete()

Extracting to Function

# Extract method to a module-level function
method.extract_to_function("helper_process")

Function Operations

Functions support the same operations as methods:

func = rj.file("utils.py").find_function("process")

func.rename("process_data")
func.add_decorator("lru_cache")
func.insert_statement("logger.debug('Starting')", position="start")
func.add_parameter("verbose", type_annotation="bool", default_value="False")
func.set_return_type("ProcessResult")
func.delete()

File Operations

Adding Imports

file = rj.file("mymodule.py")

file.add_import("from typing import Optional")
file.add_import("import json")
file.add_import("from myapp.utils import helper")

Organizing Imports

file.organize_imports()           # Sort and group imports
file.remove_unused_imports()      # Remove imports not used in file
file.add_missing_imports()        # Add imports for undefined names

Converting Import Styles

file.convert_relative_to_absolute()   # from .utils → from mypackage.utils
file.convert_absolute_to_relative()   # from mypackage.utils → from .utils

Adding Functions/Classes

file.add_function("main", body="print('Hello')")
file.add_class("Config", body="DEBUG = True")

Async Conversions

func = rj.find_functions("fetch_data").first()

# Convert sync to async
func.convert_to_async()

# Convert async to sync
func.convert_to_sync()

Docstrings

Generating

func.generate_docstring(style="google")  # or "numpy", "sphinx"
cls.generate_docstrings()  # Generate for all methods

Updating

method.update_docstring_param("timeout", "Maximum wait time in seconds")
method.add_docstring_raises("ValueError", "If input is negative")
method.add_docstring_example(">>> process(5)\\n10")
method.add_docstring_returns("The processed result")

Converting Styles

file.convert_docstring_style("google", "numpy")

Type Hint Modernization

# Modernize type hints (Python 3.10+ style)
file.modernize_type_hints()  # List[str] → list[str], Optional[X] → X | None

# Convert type comments to annotations
file.convert_type_comments_to_annotations()  # # type: str → : str

Class Conversions

cls = rj.find_classes("Config").first()

# Convert to dataclass
cls.convert_to_dataclass()

# Convert from dataclass
cls.convert_from_dataclass()

# Other conversions
cls.convert_to_typed_dict()
cls.convert_to_named_tuple()

Generating Dunder Methods

cls.generate_init()
cls.generate_repr()
cls.generate_eq()
cls.generate_hash()
cls.generate_all_dunders()  # All of the above

Properties

# Convert attribute to property
cls.convert_attribute_to_property("_name", getter=True, setter=True)

# Add a computed property
cls.add_property("full_name", getter="return f'{self.first} {self.last}'")

Converting Format Strings

File-level helpers convert old-style string formatting to f-strings:

file = rj.file("legacy_module.py")

# "Hello {}".format(name) → f"Hello {name}"
file.convert_format_strings_to_fstrings()

# "Hello %s" % name → f"Hello {name}"
file.convert_percent_format_to_fstrings()

Result Handling

All operations return a Result:

result = cls.rename("NewName")

if result:
    print(f"Modified: {result.files_changed}")
else:
    print(f"Failed: {result.message}")
    if result.exception:
        result.raise_if_error()  # Re-raise if you want

Next Steps