Plan completo de migración para DataFlow Analytics — de legacy pip/flake8/mypy al stack Astral moderno.
# ────────────────────────────────────────────────────────────────────── # dataflow-pipeline · pyproject.toml (generado con uv init --package) # ────────────────────────────────────────────────────────────────────── [project] name = "dataflow-pipeline" version = "2.0.0" description = "SaaS B2B predictive analytics pipeline for e-commerce" requires-python = ">=3.11" readme = "README.md" license = "UNLICENSED" authors = [{name = "DataFlow Engineering", email = "eng@dataflow.io"}] dependencies = [ "pandas>=2.1", "polars>=0.20", "duckdb>=0.10", "fastapi>=0.110", "uvicorn[standard]>=0.28", "openai>=1.30", "anthropic>=0.25", ] [build-system] requires = ["uv_build"] # reemplaza hatchling/setuptools build-backend = "uv_build" # ── Grupos de dependencias (PEP 735) — NUNCA usar optional-dependencies ── [dependency-groups] dev = [{include-group = "lint"}, {include-group = "test"}, {include-group = "audit"}] lint = ["ruff", "ty"] test = ["pytest>=8", "pytest-cov", "hypothesis", "httpx"] # httpx para TestClient audit = ["pip-audit"] # ── Ruff: reemplaza flake8 + black + isort ────────────────────────────── [tool.ruff] line-length = 100 target-version = "py311" [tool.ruff.lint] select = ["ALL"] ignore = [ "D", # docstrings opcionales por ahora "COM812", # trailing comma (conflicto formatter) "ISC001", # implicit string concat (conflicto formatter) "ANN", # anotaciones — ty las gestiona ] [tool.ruff.lint.isort] known-first-party = ["dataflow_pipeline"] # ── ty: reemplaza mypy ────────────────────────────────────────────────── [tool.ty.environment] python-version = "3.11" # CORRECTO: bajo [tool.ty.environment], no [tool.ty] [tool.ty.terminal] error-on-warning = true [tool.ty.rules] possibly-unresolved-reference = "error" unused-ignore-comment = "warn" # ── pytest ───────────────────────────────────────────────────────────── [tool.pytest.ini_options] testpaths = ["tests"] addopts = [ "--cov=dataflow_pipeline", "--cov-report=term-missing", "--cov-fail-under=80", ] filterwarnings = ["error"] # warnings como errores en tests # ── Coverage ─────────────────────────────────────────────────────────── [tool.coverage.run] branch = true source = ["src/dataflow_pipeline"] [tool.coverage.report] exclude_lines = ["pragma: no cover", "if TYPE_CHECKING", "\\.\\.\\."]
# 1. Instalar uv (una vez por máquina) $ curl -LsSf https://astral.sh/uv/install.sh | sh # 2. Inicializar uv en el proyecto existente $ uv init --bare # no sobreescribe src/ # 3. Migrar dependencias desde requirements.txt $ grep -v '^#' requirements.txt | while read pkg; do uv add "$pkg" || echo "⚠ Failed: $pkg" done $ grep -v '^#' requirements-dev.txt | while read pkg; do uv add --group dev "$pkg" done # 4. Eliminar herramientas legacy $ uv remove flake8 black isort mypy # 5. Añadir stack moderno $ uv add --group lint ruff ty $ uv add --group audit pip-audit # 6. Sincronizar todo el entorno $ uv sync --all-groups # 7. Primer lint (con autofix) $ uv run ruff check --fix . $ uv run ruff format . # 8. Type check inicial $ uv run ty check src/ # 9. Tests con cobertura $ uv run pytest # 10. Auditoría de seguridad $ uv run pip-audit # 11. Limpiar archivos legacy $ rm -f requirements.txt requirements-dev.txt setup.py $ rm -rf .flake8 mypy.ini .pre-commit-config.yaml $ git add uv.lock pyproject.toml $ git commit -m "chore: migrate to uv+ruff+ty stack"
.PHONY: dev lint format test build audit dev: ## Instalar todas las deps uv sync --all-groups lint: ## Lint + format check + tipos uv run ruff format --check . uv run ruff check . uv run ty check src/ format: ## Auto-formatear código uv run ruff format . uv run ruff check --fix . test: ## Tests + cobertura uv run pytest audit: ## Seguridad de dependencias uv run pip-audit build: ## Build distributable uv build ci: lint test audit ## Todo junto (CI)
uv init --bare en el reponame: CI on: [push, pull_request] jobs: lint-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v3 with: enable-cache: true # uv.lock caching - name: Sync dependencies run: uv sync --all-groups - name: Lint run: | uv run ruff format --check . uv run ruff check . uv run ty check src/ - name: Test run: uv run pytest - name: Audit run: uv run pip-audit
# /// script # requires-python = ">=3.11" # dependencies = [ # "polars>=0.20", # "duckdb>=0.10", # "rich>=13", # ] # /// import polars as pl from rich.progress import track # Ejecutar con: uv run migrate_events.py # uv resuelve las deps automáticamente
| Comando | Descripción | Equivalente legacy |
|---|---|---|
| uv add pandas | Añadir dependencia de producción | pip install pandas + editar requirements.txt |
| uv add --group dev ruff | Añadir a grupo de desarrollo | pip install ruff + requirements-dev.txt |
| uv remove mypy | Eliminar paquete | pip uninstall + editar requirements |
| uv sync --all-groups | Instalar todas las dependencias | pip install -r requirements.txt -r requirements-dev.txt |
| uv run pytest | Ejecutar en el entorno gestionado | source .venv/bin/activate && pytest |
| uv run --with httpx python -m ... | Dep temporal sin instalar | pip install httpx && python -m ... && pip uninstall httpx |
| uv build | Construir wheel/sdist | python setup.py bdist_wheel |
| uv publish | Publicar a PyPI (o registro interno) | twine upload dist/* |
uv remove mypy && uv add ty.