Skip to main content

Semantic upgrade assistant and compatibility codemods for Python dependencies.

Project description

PyCompatRepair (pycomprepair)

CI PyPI version PyPI downloads License: Apache 2.0 Python versions Code style: ruff Checked with mypy

Asistente de upgrades semánticos y codemods de compatibilidad para dependencias Python.

pycomprepair analiza el código de tu proyecto frente a una versión actual y una versión objetivo de una librería, detecta call-sites incompatibles y aplica codemods verificables con --dry-run, diff legible y posibilidad de rollback.

A diferencia de herramientas como pyupgrade (solo sintaxis del lenguaje) o bump-pydantic (solo Pydantic v1→v2), pycomprepair está pensado como un núcleo extensible con un sistema de plugins por ecosistema. El MVP incluye:

  • Núcleo: extracción de firmas con griffe, detección de incompatibilidades, motor de codemods sobre libcst.
  • Plugin Pydantic v2: BaseSettings, Configmodel_config, @validator@field_validator, .dict().model_dump(), .parse_obj().model_validate(), etc.
  • Plugin FastAPI: deprecated on_eventlifespan, Depends con use_cache deprecated, etc.
  • Plugin SQLAlchemy 2.0: from sqlalchemy.ext.declarative import declarative_basesqlalchemy.orm, session.query(M).get(pk)session.get(M, pk), avisos sobre declarative_base() y Query.update/delete.
  • Plugin Django 5.0: smart_text/force_textsmart_str/force_str, ugettext*gettext*, aviso sobre django.utils.timezone.utc y Meta.index_together.
  • Plugin NumPy 2.0: alias escalares eliminados (np.floatfloat, np.intint, …), constantes (np.NaNnp.nan, np.Infnp.inf) y renombrados de funciones (np.productnp.prod, np.alltruenp.all, np.round_np.round, …).
  • CLI (pycomprepair) con scan, repair, report.

Instalación

pip install pycomprepair

o, si usas uv:

uv pip install pycomprepair

Requiere Python 3.10+.

Para desarrollo local sobre el repositorio:

uv venv
uv pip install -e ".[dev]"

Uso rápido

# Escanear el proyecto y detectar incompatibilidades
pycomprepair scan ./src --target "pydantic>=2.0,<3.0"

# Aplicar codemods en modo dry-run (muestra diff, no escribe)
pycomprepair repair ./src --target "pydantic>=2.0,<3.0" --dry-run

# Aplicar de verdad
pycomprepair repair ./src --target "pydantic>=2.0,<3.0"

# Generar reporte HTML/Markdown
pycomprepair report ./src --target "pydantic>=2.0,<3.0" --format markdown

Configuración por proyecto

Para evitar repetir --target y demás flags en cada llamada, PyCompatRepair lee configuración de un fichero pycomprepair.toml (o de una sección [tool.pycomprepair] en tu pyproject.toml). La búsqueda sube por los directorios padre desde la ruta que pases en la CLI, así que puedes ponerlo en la raíz del repo:

# pycomprepair.toml
target = "pydantic>=2.0,<3.0"
min_confidence = 0.8
unsafe_fixes = false
ignore = ["PYD002", "DJA004"]  # códigos de regla que no quieres ver

Equivalente dentro de pyproject.toml:

[tool.pycomprepair]
target = "pydantic>=2.0,<3.0"
ignore = ["PYD002"]

Los flags de la CLI tienen prioridad sobre la configuración, y la configuración sobre los valores por defecto. Con esto, pycomprepair scan ./src ya basta una vez configurado el proyecto.

Descubrimiento dinámico (discover)

Más allá de los plugins manuales, pycomprepair puede consultar la API real de un paquete instalado mediante griffe y avisarte de imports que ya no existen en esa versión. Es la forma más rápida de auditar tu código frente al venv objetivo:

# Crea un venv con la versión a la que quieres migrar
uv pip install "django==5.0.*"

# Encuentra imports rotos respecto a la Django instalada
pycomprepair discover ./src --package django

Cada importación cuyo símbolo no figura en la API cargada genera un issue DSC001. A partir de la 0.2.0, discover además realiza un análisis ligero de accesos a atributos (código DSC002) que detecta usos del tipo:

import numpy as np
x = arr.astype(np.float)              # DSC002: numpy.float fue eliminado

import django
ts = django.utils.timezone.utc        # DSC002: removido en Django 5.0

El análisis es conservador: ignora nombres reasignados, parámetros de función y cualquier cadena que pase por una función (su valor de retorno es opaco), de modo que el ruido en CI es muy bajo. Esto convierte a discover en un linter semántico de compatibilidad y no solo en un verificador de imports.

Salida SARIF para GitHub Code Scanning

pycomprepair report puede emitir SARIF 2.1.0 para integrarse de forma nativa con la pestaña Security → Code scanning de GitHub:

pycomprepair report ./src --target "django>=5.0,<5.1" \
  --format sarif --output pycomprepair.sarif

En el workflow:

- run: pycomprepair report ./src --target "django>=5.0" --format sarif --output pcr.sarif
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: pcr.sarif
    category: pycomprepair

Cada regla aparece deduplicada en tool.driver.rules con su severidad por defecto y cada issue se sube como un result con physicalLocation que apunta al fichero (ruta relativa al directorio escaneado) y la línea/columna exacta.

Pre-commit

PyCompatRepair publica pre-commit-hooks.yaml, así que basta con añadirlo a tu .pre-commit-config.yaml:

repos:
  - repo: https://github.com/alvaroo-fdez/pycomprepair
    rev: v0.2.0
    hooks:
      - id: pycomprepair-scan
      # Opcionalmente, valida también contra la API instalada:
      - id: pycomprepair-discover
        args: ["--package", "django"]

Hooks disponibles:

Hook Equivalente CLI
pycomprepair-scan pycomprepair scan .
pycomprepair-repair-check pycomprepair repair . --dry-run
pycomprepair-discover pycomprepair discover . (+ paquetes)

Úsalo como GitHub Action

PyCompatRepair se distribuye también como composite action, así que puedes añadir un job de compatibilidad a cualquier repositorio Python en cinco líneas:

# .github/workflows/pycomprepair.yml
name: Compatibility check
on: [pull_request]
permissions:
  contents: read
  pull-requests: write  # solo si activas comment-on-pr

jobs:
  pycomprepair:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: alvaroo-fdez/pycomprepair@main
        with:
          path: src
          target: "pydantic>=2.0,<3.0"
          mode: scan            # "scan" (default) o "repair"
          fail-on-issues: "true"
          comment-on-pr: "true" # publica/actualiza un comentario idempotente

Inputs principales:

Input Default Descripción
path . Ruta a escanear/reparar.
target Requisito objetivo, p.ej. "pydantic>=2.0,<3.0".
mode scan scan solo detecta; repair además incluye diffs en el reporte.
fail-on-issues true Falla el job si se detectan incompatibilidades.
comment-on-pr false Publica/actualiza un comentario en el PR con el reporte (idempotente).
version Especificador opcional, p.ej. ==0.1.0 para fijar versión.
git-ref Instala desde un ref del repo (útil para probar cambios sin publicar).
skip-install false Salta la instalación si ya tienes pycomprepair en el PATH.

El reporte siempre se publica en el step summary del job; los outputs issues-count y report-path quedan disponibles para pasos posteriores.

Arquitectura

src/pycomprepair/
├── core/           # Diff de firmas, registro de plugins, modelos de issue
├── codemods/       # Helpers libcst reutilizables
├── plugins/        # Plugins por ecosistema (pydantic, fastapi, ...)
├── report/         # Renderers Markdown/HTML
└── cli.py          # CLI Typer

Licencia

Apache-2.0. Ver LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pycomprepair-1.0.0.tar.gz (69.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pycomprepair-1.0.0-py3-none-any.whl (70.4 kB view details)

Uploaded Python 3

File details

Details for the file pycomprepair-1.0.0.tar.gz.

File metadata

  • Download URL: pycomprepair-1.0.0.tar.gz
  • Upload date:
  • Size: 69.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pycomprepair-1.0.0.tar.gz
Algorithm Hash digest
SHA256 108feb7f147c218ebdad751df45c3a224528cb31c72120ce0aa22ce242954935
MD5 e392bb84edf83360934042e2cce6e65c
BLAKE2b-256 05c946c5838ae8ed11bb01d1747beeeda0cbaf85471308b7a3f59ee860d3b2b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pycomprepair-1.0.0.tar.gz:

Publisher: release.yml on alvaroo-fdez/pycomprepair

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pycomprepair-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: pycomprepair-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 70.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pycomprepair-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3156e188da1d1ba4cc5fd8da2057f215eb4fdd4b2032daad5124f023fd12abb9
MD5 1596c7ad8ce9188c353c37d4efc22924
BLAKE2b-256 8026c389d49f045999b6e4ff7218c0ed53bf48502691700513b0cb7576bd28bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pycomprepair-1.0.0-py3-none-any.whl:

Publisher: release.yml on alvaroo-fdez/pycomprepair

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page