Change Signature
Relevant source files
The following files were used as context for generating this wiki page:
The Change Signature refactoring in the Rope library provides a mechanism to modify the parameters of a Python function or method. This includes adding new arguments, removing existing ones, reordering parameters, and handling default values. The refactoring ensures that both the function definition and all its call sites across the project are updated consistently to maintain code correctness.
This feature is implemented as a specialized refactoring class that leverages Rope's code analysis capabilities to find occurrences of the target function and calculate the necessary Change objects. It integrates closely with the project's History system to allow for previews and undos of the operation.
Sources: rope/refactor/change_signature.py:1-25, rope/base/change.py:11-20
Core Architecture
The system is built around the ChangeSignature class, which orchestrates the identification of the function, the calculation of argument mappings, and the generation of code changes.
Key Components
| Component | Description |
|---|---|
ChangeSignature | The primary entry point that validates the target and generates the ChangeSet. |
_FunctionChangers | An internal coordinator that applies a sequence of argument modifications to a function's signature and call sites. |
_ArgumentChanger | Base class for specific modification types (Add, Remove, Reorder, Normalize, Inline Default). |
_ChangeCallsInModule | Handles the actual source code transformation within a specific module by using a ChangeCollector. |
Sources: rope/refactor/change_signature.py:13-30, rope/refactor/change_signature.py:126-150
Workflow Diagram
The following diagram illustrates the high-level flow from initializing the refactoring to generating changes across multiple files.
Argument Transformation Logic
The refactoring uses DefinitionInfo to read the current state of a function and ArgumentMapping to determine how call site arguments should be shifted or modified.
Argument Changers
Specific classes inherit from _ArgumentChanger to implement different refactoring behaviors:
- ArgumentRemover: Deletes a parameter at a specific index. If the parameter is assigned at a call site, it is removed from the
param_dict. - ArgumentAdder: Inserts a new parameter. If a
valueis provided, that value is added to all existing call sites. - ArgumentReorderer: Changes the order of parameters based on a provided index list. It can also apply "automatic defaults" (
autodef) if a non-default argument is moved after a default argument. - ArgumentDefaultInliner: Replaces a parameter at a call site with its default value from the definition.
Sources: rope/refactor/change_signature.py:161-235
Mapping and Call Update Flow
Occurrence Finding and Selection
The refactoring identifies targets using rope.refactor.occurrences. It handles standard functions, class methods (optionally within a hierarchy), and class constructors.
Hierarchy and Constructors
- Methods: If
in_hierarchyis enabled, the refactoring finds and modifies matching method signatures in base and sub-classes. - Class Initialization: If the refactoring is performed on a class name (at the call site) or its
__init__method, Rope identifies both the constructor definition and the class instantiation calls.
Sources: rope/refactor/change_signature.py:33-47, rope/refactor/change_signature.py:53-65
Implementation Details
The actual text replacement is performed by _ChangeCallsInModule. It uses worder.Worder to identify the range of parentheses for function calls and definitions.
# From rope/refactor/change_signature.py:250-258
for occurrence in self.occurrence_finder.find_occurrences(self.resource):
if not occurrence.is_called() and not occurrence.is_defined():
continue
start, end = occurrence.get_primary_range()
begin_parens, end_parens = word_finder.get_word_parens_range(end - 1)
if occurrence.is_called():
primary, pyname = occurrence.get_primary_and_pyname()
changed_call = self.call_changer.change_call(
primary, pyname, self.source[start:end_parens]
)
Sources: rope/refactor/change_signature.py:245-265
Summary
The Change Signature module provides a robust way to evolve Python APIs by automating the tedious task of updating call sites. By utilizing a pipeline of _ArgumentChanger objects, Rope can perform complex transformations—such as simultaneously adding, removing, and reordering arguments—while ensuring that the resulting code adheres to Python's syntax rules regarding default arguments and keyword parameters.