Python pratico

Automatizzare la ridenominazione sicura di variabili con rope

6 min di lettura
Due foglietti su scrivania scura: tmp cerchiato in terracotta e invoice_total con spunta, laptop chiuso sullo sfondo
Windows macOS Linux
Foto: Alex Lunalbi · ai riparo · Proprietario

Rinomina variabili in Python in modo sicuro con rope: niente sostituzioni cieche. Setup in venv, un esempio concreto e come verificare il diff.

Quando generi script con l’IA o assembla pezzi da chat diverse, il codice può funzionare con nomi pessimi: data, temp, result2, x sparsi ovunque.

Correggerli a mano o con «Trova e sostituisci» può rompere stringhe, commenti e omonimi in altri scope. Questo micro, spoke del refactoring automatico con AST, Ruff e Rope, mostra come usare rope per un rename scope-aware: solo i riferimenti al simbolo giusto.

ℹ️ Prerequisito: Python 3.11+ (lab verificato con Rope 1.15.x). Lavora in un venv. Per la mappa degli indizi prima del rename, vedi lo scanner AST.

Perché «Trova e sostituisci» non basta

Ctrl+H / Cmd+H tratta il file come testo. Non distingue variabili, funzioni e letterali.

def calcola_totale(data):
    # Processiamo i data
    log_message = "Analisi della variabile data iniziata"
    return sum(data)

def aggiorna_data_database(nuova_data):
    print(nuova_data)

Se sostituisci cieco data → valori_input:

  • il commento cambia (rumore);
  • la stringa cambia (output/test possono rompersi);
  • aggiorna_data_database diventa aggiorna_valori_input_database (simbolo sbagliato).

Serve uno strumento che ragioni sull’AST, non sulle sottostringhe.

Cos’è rope e come ragiona

Rope è una libreria Python orientata al refactoring semantico. Diverso da Ruff (lint/format veloce): rope modifica struttura.

In un rename tipico:

  1. apre un Project (grafo dei moduli nella cartella);
  2. individua il simbolo all’offset (posizione carattere del cursore);
  3. trova i riferimenti a quell’oggetto nello scope corretto;
  4. applica le modifiche (anche cross-file, se il progetto le include).

Molti IDE usano motori simili dietro il rename. Qui usiamo l’API per capire l’offset e automatizzare il lab.

Preparare l’ambiente

Non installare rope nel Python globale.

Windows (PowerShell):

python -m venv venv
.\venv\Scripts\Activate.ps1
python -m pip install rope

macOS / Linux:

python3 -m venv venv
source venv/bin/activate
python3 -m pip install rope
python -c "import rope; print('Rope OK')"

Laboratorio: tmp → invoice_total

1. File di partenza

Crea demo.py:

# demo.py

def calcola_fattura(prezzi):
    tmp = sum(prezzi)

    # Questo commento cita tmp, ma non deve cambiare
    stato = "Calcolato tmp"

    if tmp > 100:
        return tmp * 0.90  # Sconto del 10%
    return tmp

def altra_funzione(tmp):
    # Questo è un altro 'tmp' in uno scope diverso.
    # Non deve essere toccato dalla nostra ridenominazione.
    return tmp + 1

2. Script di ridenominazione

L’offset è l’indice del carattere su cui «punti» il cursore. Nello script usiamo find('tmp =') come espediente didattico (in IDE arriva dal cursore / LSP).

🚨 Modifica file: lo script sovrascrive demo.py. Su codice reale: commit Git prima.

Crea esegui_rename.py:

# esegui_rename.py
import os
from rope.base.project import Project
from rope.refactor.rename import Rename


def rinomina_variabile() -> None:
    percorso_progetto = os.path.abspath(".")
    progetto = Project(percorso_progetto)
    risorsa = progetto.get_resource("demo.py")
    codice = risorsa.read()

    # Espediente lab: prima definizione "tmp =".
    # In produzione: offset dal cursore IDE / da AST (lineno+col).
    target = "tmp ="
    offset = codice.find(target)
    if offset == -1:
        print("Variabile non trovata.")
        return

    print(f"Variabile trovata all'offset {offset}.")
    refactoring = Rename(progetto, risorsa, offset)
    cambiamenti = refactoring.get_changes("invoice_total")
    progetto.do(cambiamenti)
    print("Ridenominazione completata.")
    progetto.close()


if __name__ == "__main__":
    rinomina_variabile()
python esegui_rename.py

Output tipico verificato nel lab: Variabile trovata all'offset 44. poi conferma di completamento.

Come verificare il risultato

demo.py dopo Rope (lab):

# demo.py

def calcola_fattura(prezzi):
    invoice_total = sum(prezzi)

    # Questo commento cita tmp, ma non deve cambiare
    stato = "Calcolato tmp"

    if invoice_total > 100:
        return invoice_total * 0.90  # Sconto del 10%
    return invoice_total

def altra_funzione(tmp):
    # Questo è un altro 'tmp' in uno scope diverso.
    # Non deve essere toccato dalla nostra ridenominazione.
    return tmp + 1

Rope ha:

  • rinominato definizione e usi di tmp solo in calcola_fattura;
  • lasciato intatte stringa e commento;
  • ignorato il parametro tmp di altra_funzione (altro scope).

💡 Git prima e dopo: git add / commit del codice «brutto», lancia Rope, poi git diff. Se qualcosa non torna: git restore .. Meglio del controllo a occhio.

Errori comuni e casi limite

  1. SyntaxError / AST rotto — Rope non rinomina se il file non parse-a. Sistema la sintassi prima (fence markdown rimasti nel .py, parentesi aperte, …).
  2. Radice progetto sbagliata — Project('.') deve essere la cartella del lab/repo, non la home. Rope crea .ropeproject per la cache: tienila nel perimetro del progetto (e in .gitignore se non vuoi versionarla).
  3. File non salvati — Rope legge il disco. Salva l’editor prima, altrimenti offset e contenuto possono non coincidere.
  4. Dinamismo forte — getattr / setattr / eval con nomi come stringhe: l’analisi statica può non seguirli. Controlla il diff.
  5. find() fragile — se tmp = compare prima in un commento, l’offset punta lì. Mitigazione lab: pattern tmp =; in produzione usa cursore IDE o offset da AST.

Undo rapido in sessione Rope: progetto.history.undo() — comunque preferisci Git.

IDE rename vs API: quando cosa

Situazione Preferisci
Un simbolo, un file, cursore già sopra Rename dell’IDE / LSP
Capire perché non tocca stringhe/altri scope Questo lab API
Batch su più simboli / CI headless Script Rope + Git
Solo rumore stilistico (import, spazi) Ruff, non Rope

Nel vibe coding: dopo un Accept grosso, spesso basta l’IDE. Quando l’IA ha lasciato dieci tmp/data omonimi in scope diversi, l’API (o rename mirati uno alla volta) riduce il rischio di «sostituisci tutto» emotivo.

Offset da AST (cenno)

Invece di find('tmp =') puoi calcolare l’offset dal nodo:

import ast

src = open("demo.py", encoding="utf-8").read()
tree = ast.parse(src)
for node in ast.walk(tree):
    if isinstance(node, ast.Assign):
        for t in node.targets:
            if isinstance(t, ast.Name) and t.id == "tmp":
                # byte offset: somma lunghezze righe precedenti + col_offset
                lines = src.splitlines(keepends=True)
                offset = sum(len(lines[i]) for i in range(t.lineno - 1)) + t.col_offset
                print("offset", offset)

Poi passi quell’offset a Rename(...). Più verboso, meno fragile del find su file lunghi.

Domande Frequenti (FAQ)

Cos’è rope in Python?

Libreria open source di refactoring basata sull’AST: rename, extract, move, ecc.

Differenza con «Trova e sostituisci»?

Il primo è testuale; rope è scope-aware e distingue stringhe/commenti dai simboli (nei limiti dell’analisi statica).

Come lo installo?

Nel venv: python -m pip install rope (o python3 -m pip …).

È sicuro al 100%?

No. È accurato sui simboli statici tipici, ma può mancare riferimenti dinamici. git diff obbligatorio.

Rename su più file?

Sì, se il Project include i moduli: aggiorna definizione, import e chiamate nel perimetro analizzato.

Rope vs Ruff?

Complementari. Nella pipeline madre: Ruff (format/import) → Rope (rename) → Ruff check → review 15 minuti.

Devo usare l’API o basta l’IDE?

Per un rename singolo, l’IDE basta. L’API serve a capire l’offset, a lab riproducibili e a batch headless.

In sintesi

  1. Non rinominare a occhio con sostituzione cieca.
  2. Rope punta un offset, risolve lo scope, aggiorna solo i riferimenti giusti.
  3. Commit → rename → git diff → test smoke.
  4. Poi rientra nel flusso completo AST → Ruff → Rope della guida madre.

Letture opzionali

Alex Lunalbi

Alex Lunalbi

Security & privacy

Dona su PayPal

Scrivo di sicurezza digitale pratica e codice IA. Su ai riparo ogni procedura è verificata su macchine reali.

Tag
  • python,
  • rope,
  • refactoring,
  • vibe coding