🛠️ Tooling moderno para Python 🐍
Martín Gaitán @ 
DevEx (DX): Experiencia del desarrollo de software
«Herramientas y procesos para hacer el trabajo de quienes crean software más fácil y productivo»
¿Y quienes crean software?
Tod@s nosotres! Devs, PM, soporte, infra y agentes.
Pd: Developer Development Experience
Momento «yo»
Tools + docs (+ agentes), FTW!
El tooling de Python no era pythonico
setup.pymisteriosos (setuptoolsy más viejos)Dependencias inseguras y lentas (
pipy más viejos)Aislacion de entornos complejo (
virtualenv)Linting/formatters dispersos y lentos (
black,flake8+ plugins)Test framework feísimo (
unittest)Tipado estático complejo y lento (
mypy)
💡 Un lenguaje excepcional merece herramientas excepcionales.
Pero un día llegó el doctor…
…manejando un cuatrimotor (oxidado 🦀)
Pieza 1: uv
uv’s mini cheatsheet
uv add # resuelve y agrega depedencias al proyecto
uv run <comando> # ejecuta un comando provisto en el proyecto (o dependencia)
uv run script.py # ejecuta el script
uv run -p 3.13 ... # version de Python especifica
uv tool install <tool> # descarga y deja la tool disponible
uv python install 3.15 # descarga e instala Python estático en cualquier OS
uv build --wheel # produce el ".whl" del paquete
uv pip install ... # "pip compatible" (buuuh!)
uvx: shortcut para instalar en venv y ejecutar
Eg. uvx textual-tetris
Estándares modernos
Todo en
pyproject.tomlen vez desetup.py + setup.cfg + Manifest.in + requirements.in|txt + flake8.ini + pytest.ini + ...
PEP723
uv run script.py
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
Locking de dependencias
Eg.
greenlet>=3.0. -> Sale 4.0 y 💣!No más «En mi compu funciona»
Ahora
uv.lockes la fuente de verdad.Lo versionamos en proyectos, no en libs.
Pieza 2: Ruff
¿Cómo dice?
uv run ruff check <path/to/file(s)>
uv run ruff format <path/to/file(s)>
uv no ejecuta codigo, lo analiza y transforma estáticamente
¿Reglas?
¡Somos Fierro y manda el facón!
Las clasicas de flake8 y pyflake
Bandit/Bugbear: patrones con bugs/issue de seguridad
DTZ: errores en manejo de fechas
Simplify: reescribir lo mismo más «pythonico»
Isort/TDI: imports
PERF: mejoras en performance
UP/FURB: modernizar código a idioms nuevos
Pep8-naming: la parte PEP8 que no respetamos 🥺
decenas más
¿Aguantarse la pelusa? ¿cuánta?
$ uv run ruff check .
....
Found 6316 errors.
[*] 2035 fixable with the `--fix` option (585 hidden fixes can be enabled with the `--unsafe-fixes` option).
$ uv run ruff format --check .
...
1185 files would be reformatted, 468 files already formatted
Con las reglas que suelo usar
Found 174027 errors.
[*] 10636 fixable with the `--fix` option (31229 hidden fixes can be enabled with the `--unsafe-fixes` option).
Autofixes
--fix: 100% confiable. Pero hacer PRs adhoc para no meter ruido.--fix --unsafe-fixes: confiables, pero leer la doc de la regla por corner cases y revisar con calma.🤖 «ejecutá ruff check –fix en los archivos modificados y corregí los errores que queden»
📌 integrá ruff en tu editor (highlight de error + autofix en el save)
Adopción incremental
Más?
ty-> extremely fast Python type checker and language serverpytest -> estándar de facto para tests (framework/runner)
Mi template https://github.com/mgaitan/python-package-copier-template