Elegir espacio

Dos espacios

¿Qué quieres consultar?

Elige el espacio al que quieres entrar.

Biblioteca FastAPIPráctica

Práctica · Bloque 3 · Unidades 3.1–3.2

Compón la aplicación sin ocultar su comportamiento

Un refactor no termina cuando aparecen carpetas o `Depends`. Termina cuando puedes demostrar qué contrato se conserva, qué proveedor se ejecuta, cuánto vive su resultado y cómo se libera incluso al fallar.

Cómo trabajar este bloque

Antes de modularizar: Calcula las rutas finales a partir de los prefijos y dibuja la dirección de imports antes de mover una línea.

Antes de proporcionar recursos: Dibuja el árbol desde la operación hasta cada proveedor y predice cuáles se ejecutan una vez por petición, una vez por proceso o alrededor de la respuesta.

Usa un workspace temporal. Conserva un baseline verde, mueve una sola frontera y repite exactamente la misma observación. Los paquetes no incluyen una solución modular, un árbol de dependencias resuelto ni tests ocultos que dicten carpetas.

Ver la reflexión guardada del ejercicio guiado

6 actividades disponibles.

Paso 5 · Apoyo focalizado

Extrae una sola frontera

Evidencia: El diff mueve código, pero status, body, modelos de salida, operationId y paths públicos permanecen estables.

EX-B3-01

Extraer el primer router sin cambiar el contrato

  • Respuesta redactada
  • Refactor guiado
  • Media

Una aplicación de expedientes ya tiene tests y tres operaciones públicas, pero main.py mezcla arranque, schemas, estado y rutas.

Pensar y responder en la web

Predice y guarda aquí tu razonamiento antes de abrir el material; después contrástalo en el workspace.

Pregunta central

¿Qué paths deben quedar en decoradores y prefijos para que el contrato final no cambie, y qué import debe apuntar hacia el punto de composición?

Frontera que debes preservar

Contrato inicial: GET /health, POST /expedientes y GET /expedientes/{expediente_id}. El include no aporta prefijo adicional.

Para ordenar tu razonamiento

  1. ¿Qué conjunto método/path existe antes de mover código?
  2. ¿Qué suma de prefijos produce cada URL final?
  3. ¿Qué import crearía una vuelta hacia main.py?

Trabajo en el workspace

  1. Ejecuta los tests y registra las operaciones generadas por app.openapi().
  2. Completa el mapa de prefijos y el grafo de imports antes de mover código.
  3. Extrae schemas y un APIRouter de expedientes; conserva main.py como punto de composición.
  4. Ejecuta la misma regresión y explica cualquier diferencia antes de corregirla.

Entrega esperada

  • Árbol final y grafo de imports dirigido.
  • Diff acotado del refactor.
  • Evidencia de pytest y fingerprint OpenAPI antes y después.

Escribe lo que piensas. Se guarda automáticamente en este navegador.

Sin respuesta guardada.

Pistas opcionales

Pista 1 · Conserva la suma
  • Si el router tiene prefix=/expedientes, el decorador de colección puede usar una cadena vacía.
  • El prefijo de include también participa aunque no esté en el archivo del router.
Pista 2 · Corta la vuelta
  • El módulo de rutas exporta router; main.py lo importa e incluye.
  • Un módulo inferior no necesita importar main.py para registrarse.
Profundización opcional

Extraer las operaciones de expedientes a APIRouter mediante un corte pequeño y demostrar compatibilidad HTTP y OpenAPI.

Contexto adicional

  • No añadas endpoints, capas ni modelos durante el refactor.
  • Conserva nombres públicos, status, bodies, response_model y operationId.
  • Haz pasar la regresión después de extraer un solo router.

Decisiones abiertas

  • Puedes usar imports absolutos o relativos, pero debes mantener una convención y explicar la dirección.
  • Puedes dejar /health en main.py o justificar un router operacional; no crees ese router solo por simetría.

Cómo revisar tu respuesta

  • Los tres pares método/path permanecen iguales.
  • Status, body y response_model pasan la regresión existente.
  • El router no importa la instancia app ni existe registro por efecto lateral.
  • La explicación identifica una decisión que deliberadamente quedó fuera.

Evidencia, revisión y reinicio

  • Predicción de rutas finales y grafo de imports antes del cambio.
  • Salida de pytest y conjunto método/path de OpenAPI antes y después.
  • Diff que mueve un grupo de operaciones sin añadir funcionalidad.

Revisión: con Codex, utilizando la evidencia y los criterios anteriores; no se publica una solución oficial.

Reinicio: Restaurar el módulo monolítico descargado y borrar los paquetes creados; no existe estado externo.

Material descargable opcional

Checkpoint independiente · EX-B3-S01-01

Repite la modularización en otro dominio

En un dominio distinto y sin una secuencia de archivos prescrita, modularizas la aplicación y justificas su grafo de imports.

EX-B3-S01

Flujo de solicitudes de cumplimiento

  • Práctica extendida
  • Checkpoint acumulativo
  • Media-alta
  • Apoyo autónomo; criterios visibles, sin pistas ni árbol prescrito
  • M-MIN

Recibes una API distinta a la del ejemplo: registra solicitudes de cumplimiento, permite consultarlas y tomar una decisión. Funciona y está probada, pero vive en un único módulo.

Abrir práctica extendida: base común y 1 parte

Base común

  • El starter arranca y sus tests deben estar verdes antes de editar.
  • El contrato público y los datos sintéticos son distintos al ejercicio guiado.
  • Cada parte declara qué mecanismo puede añadirse; persistencia, autenticación, servicios y auto-registro siguen fuera.
  • Los criterios dicen qué conservar, no qué carpetas debes crear.

Paquete de trabajo

Entorno, evidencia y reinicio

Entorno: Python 3.10+ en un workspace temporal; FastAPI, Pydantic 2, pytest y httpx2 instalados por el paquete con uv.

  • Commit o diff del refactor sin cambios funcionales.
  • Salida completa de pytest antes y después.
  • Fingerprint OpenAPI y diagrama de imports final.

Revisión: con Codex, utilizando los artefactos y criterios de cada parte; no se publica una solución oficial.

Reinicio: Descomprimir de nuevo el starter en otro directorio temporal; cada intento empieza con el monolito y sus tests verdes.

Parte 1 · Apoyo autónomo

EX-B3-S01-01 · Separar routers y schemas

Modularizar un contexto nuevo sin copiar el árbol del ejemplo y defender cada frontera mediante evidencia de regresión.

Qué debes hacer
  1. Sin abrir las pistas de EX-B3-01, predice las rutas finales y dibuja el grafo de imports que quieres conseguir.
  2. Ejecuta el baseline y guarda el fingerprint de operaciones y operationId.
  3. Separa composición, frontera HTTP y schemas con la estructura mínima que puedas justificar.
  4. Repite la regresión, inspecciona OpenAPI y documenta una separación que decidiste no hacer.
Entrega esperada
  • Repositorio refactorizado sin funcionalidad nueva.
  • before-after.md con comandos, resultados y diferencias observadas.
  • Diagrama breve de imports y nota de decisión arquitectónica.
Criterios de aceptación
  • Los seis tests suministrados pasan antes y después.
  • Los cuatro pares método/path y sus operationId no cambian.
  • No hay imports desde routers o schemas hacia main.py.
  • La aplicación registra routers de forma explícita y un módulo omitido desaparece de OpenAPI de forma diagnosticable.
  • La entrega explica por qué la estructura elegida es suficiente ahora y dónde se detuvo el refactor.
Evidencia para revisión
  • Predicción y fingerprint previos al cambio.
  • Diff, árbol y grafo de imports finales.
  • Misma salida de pytest y mismo contrato público al terminar.

Reinicio de esta parte: Volver a descomprimir el starter; no reutilizar módulos del ejercicio guiado.

Transferencia: Ante otra aplicación monolítica, puedes decidir qué separar ahora, qué dejar junto y cómo demostrar compatibilidad.

Paso 6 · Retirada gradual del apoyo

Observa cada reloj por separado

Evidencia: OpenAPI conserva sus parámetros, la configuración falla pronto y el recurso se libera tanto en éxito como en error.

EX-B3-03

Construir y observar un árbol de dependencias

  • Respuesta redactada
  • Laboratorio guiado
  • Media

Dos ramas de una consulta de informes repiten headers y normalización de correlación. El contrato funciona, pero no permite observar ni reutilizar el requisito común.

Pensar y responder en la web

Predice y guarda aquí tu razonamiento antes de abrir el material; después contrástalo en el workspace.

Pregunta central

¿Qué nodo debe ser común a ambas ramas, qué valor entrega cada proveedor y qué evidencia distingue la caché de una ejecución accidental?

Contrato que el árbol no debe ocultar

Baseline: GET /reports exige X-Correlation-Id y X-Organization-Id, acepta page_size entre 1 y 100 y devuelve la misma representación pública.

Para ordenar tu razonamiento

  1. ¿Qué header y query deben seguir apareciendo en OpenAPI?
  2. ¿Qué hoja comparten el contexto de consulta y el de auditoría?
  3. ¿Qué cambia al enviar una segunda petición?

Trabajo en el workspace

  1. Ejecuta el baseline, inspecciona OpenAPI y dibuja el árbol que esperas.
  2. Extrae una hoja de correlación y dos proveedores que la compartan; inyecta sus valores de forma explícita.
  3. Añade una traza controlada y un test que pruebe una ejecución de la hoja en una petición y otra ejecución en la siguiente.
  4. Repite la regresión y compara los parámetros públicos antes y después.

Entrega esperada

  • Código refactorizado y tests añadidos.
  • Árbol previsto frente a traza observada.
  • Fingerprint de parámetros OpenAPI y salida de pytest antes/después.

Escribe lo que piensas. Se guarda automáticamente en este navegador.

Sin respuesta guardada.

Pistas opcionales

Pista 1 · Empieza por la hoja
  • Las dos ramas necesitan el mismo valor de correlación ya validado.
  • El resultado de una dependencia puede alimentar otra dependencia igual que alimenta una operación.
Pista 2 · Prueba dos escalas
  • Una aserción dentro de una petición prueba reutilización.
  • Otra petición debe probar que la caché anterior ya no existe.
Profundización opcional

Extraer un árbol pequeño con una subdependencia compartida y demostrar su caché por petición sin alterar el contrato HTTP u OpenAPI.

Contexto adicional

  • Conserva status, body, nombres de parámetros y validaciones públicas.
  • Usa Annotated para declarar valores concretos; no inyectes un diccionario contenedor.
  • No uses use_cache=False: la capacidad objetivo es observar el comportamiento por defecto.

Decisiones abiertas

  • Puedes ubicar los proveedores junto al router o en un módulo propio; justifica la dirección de imports.
  • Puedes trazar con una lista, un contador o un fake, siempre que la prueba restaure su estado.

Cómo revisar tu respuesta

  • El header X-Correlation-Id, X-Organization-Id y page_size conservan nombre, obligatoriedad y límites.
  • La hoja compartida se ejecuta una vez dentro de una petición aunque dos ramas la necesiten.
  • Una segunda petición produce una nueva ejecución; no existe caché entre peticiones.
  • La operación recibe valores tipados y no busca nombres dentro de un contenedor genérico.
  • Todos los tests de contrato permanecen verdes.

Evidencia, revisión y reinicio

  • Árbol previsto y traza real de resolución para dos peticiones.
  • OpenAPI y tests HTTP antes y después de extraer los proveedores.
  • Test que demuestra una sola ejecución de la subdependencia compartida por petición.

Revisión: con Codex, utilizando la evidencia y los criterios anteriores; no se publica una solución oficial.

Reinicio: Volver a descomprimir ex-b3-03-dependency-tree.zip; el paquete no usa red, base de datos ni estado externo.

Material descargable opcional

EX-B3-04

Validar settings y sustituirlos en tests

  • Respuesta redactada
  • Implementación focalizada
  • Media

Una API publica información operativa desde constantes codificadas. Los tests modifican globals y dependen del orden en que se ejecutan.

Pensar y responder en la web

Predice y guarda aquí tu razonamiento antes de abrir el material; después contrástalo en el workspace.

Pregunta central

¿Qué valores deben llegar desde el entorno, cuándo deben fallar y cómo puedes probar otro perfil sin editar la ruta ni conservar estado global?

Frontera de configuración

Baseline: GET /runtime devuelve app_name, environment y max_page_size desde constantes; audit_channel es obligatorio pero nunca se expone en la respuesta.

Para ordenar tu razonamiento

  1. ¿Qué campo debe ser obligatorio y qué default es seguro?
  2. ¿Qué prefijo evita colisiones con variables ajenas?
  3. ¿Qué estado debes restaurar al terminar el test?

Trabajo en el workspace

  1. Clasifica cada valor como regla estable, configuración pública o configuración sensible.
  2. Crea Settings con prefijo explícito, validación y un proveedor cacheado por proceso.
  3. Sustituye el proveedor en un test y demuestra que el siguiente recupera el comportamiento normal.
  4. Añade una comprobación que falle al construir Settings si falta audit_channel y documenta cuándo se ejecuta esa validación.

Entrega esperada

  • Módulo de configuración, integración y tests.
  • Matriz de fuentes y precedencia observada.
  • Salida del fallo esperado y evidencia de aislamiento entre tests.

Escribe lo que piensas. Se guarda automáticamente en este navegador.

Sin respuesta guardada.

Pistas opcionales

Pista 1 · Dos cachés
  • FastAPI reutiliza un nodo dentro de una petición.
  • functools.lru_cache conserva el resultado del proveedor entre llamadas del mismo proceso.
Pista 2 · Sustituye la función
  • La clave del mapa de overrides es el callable original, no el tipo Settings.
  • Limpia el mapa aunque la aserción falle.
Profundización opcional

Modelar configuración externa con pydantic-settings, distinguir caché de proceso y sustituir el proveedor sin contaminar otras pruebas.

Contexto adicional

  • Usa BaseSettings desde pydantic_settings y SettingsConfigDict.
  • El archivo .env es solo local y no puede entrar en el entregable; publica únicamente .env.example sin valores sensibles.
  • No reconstruyas Settings en cada request y no uses monkeypatch sobre la ruta.

Decisiones abiertas

  • Puedes validar settings al construir la app o mediante un smoke check de arranque; documenta el momento exacto del fallo.

Cómo revisar tu respuesta

  • Los nombres de entorno usan un prefijo propio y los valores se validan con tipos y límites.
  • audit_channel es obligatorio, no aparece en respuestas o logs y su ausencia falla de forma explícita.
  • El proveedor no relee el entorno en cada petición y la entrega distingue caché de proceso de caché de Depends.
  • El test reemplaza get_settings mediante dependency_overrides y restaura el mapa en finally o una fixture equivalente.
  • No se publica .env ni un secreto real; .env.example solo contiene nombres o valores ficticios.

Evidencia, revisión y reinicio

  • Matriz de fuentes y valores elegidos para local, test y producción simulada.
  • Fallo de validación con configuración obligatoria ausente.
  • Test con dependency_overrides restaurado después del intento.

Revisión: con Codex, utilizando la evidencia y los criterios anteriores; no se publica una solución oficial.

Reinicio: Volver a descomprimir ex-b3-04-settings.zip y eliminar solo el .env local creado para el intento.

Material descargable opcional

EX-B3-09

Demostrar el ciclo de vida de un recurso

  • Respuesta redactada
  • Debugging con traza
  • Media

Una ruta abre y cierra manualmente un audit sink. Otro endpoint omite el cierre al lanzar una excepción y la prueba solo comprueba el status.

Pensar y responder en la web

Predice y guarda aquí tu razonamiento antes de abrir el material; después contrástalo en el workspace.

Pregunta central

¿Qué eventos deben aparecer antes, durante y después de la operación, y qué aserción demuestra que el cleanup no depende del camino feliz?

Secuencia que debes demostrar

Traza objetivo por petición: open → use → close. El caso /audit/fail conserva su error y aun así termina en close.

Para ordenar tu razonamiento

  1. ¿Qué ocurre antes de yield?
  2. ¿Qué valor recibe la operación?
  3. ¿Qué excepción no debe desaparecer durante el cleanup?

Trabajo en el workspace

  1. Predice la traza de éxito y de fallo antes de ejecutar.
  2. Reproduce el recurso abierto después del error y conserva la evidencia.
  3. Introduce una dependencia con yield que libere en finally e inyéctala en ambas operaciones.
  4. Prueba éxito, fallo, aislamiento entre peticiones y orden de la traza.

Entrega esperada

  • Código corregido y tests de lifecycle.
  • Cronología prevista y observada para ambos caminos.
  • Explicación del scope usado y de una alternativa descartada.

Escribe lo que piensas. Se guarda automáticamente en este navegador.

Sin respuesta guardada.

Pistas opcionales

Pista única · Protege la salida
  • Crea el recurso antes de yield.
  • Coloca close en finally y deja que la excepción siga su curso.
Profundización opcional

Mover adquisición y liberación a una dependencia con yield y demostrar el orden exacto en éxito y fallo.

Contexto adicional

  • El recurso es un fake local; no añadas base de datos, red ni transacciones.
  • Usa try/finally y no conviertas el error deliberado en una respuesta exitosa.
  • Mantén la política por defecto de scope y explica cuándo se ejecuta el cierre.

Decisiones abiertas

  • Puedes registrar la traza en el fake o inyectar un recorder separado, pero su estado debe aislarse entre tests.

Cómo revisar tu respuesta

  • Cada petición abre un recurso nuevo y lo cierra exactamente una vez.
  • La traza de éxito y la de fallo terminan en close.
  • El error deliberado conserva su status y no es absorbido por la dependencia.
  • La operación usa el valor cedido y no ejecuta cleanup manual.
  • La prueba observa el estado después de completar el ciclo request/response.

Evidencia, revisión y reinicio

  • Predicción temporal para éxito y excepción.
  • Trazas open/use/close observadas por petición.
  • Tests que prueban cleanup después de 200 y después de error sin tragarse la excepción.

Revisión: con Codex, utilizando la evidencia y los criterios anteriores; no se publica una solución oficial.

Reinicio: Volver a descomprimir ex-b3-09-yield.zip; el audit sink es un fake en memoria y no abre archivos ni conexiones.

Material descargable opcional

Checkpoint independiente · EX-B3-S01-02

Integra el árbol sin copiar los ensayos

En la API modular de cumplimiento, sustituyes repetición y globals por proveedores explícitos y pruebas sus límites sin un árbol prescrito.

EX-B3-S01

Flujo de solicitudes de cumplimiento

  • Práctica extendida
  • Checkpoint acumulativo
  • Media-alta
  • Apoyo autónomo; criterios visibles, sin pistas ni árbol prescrito
  • M-MIN

Recibes una API distinta a la del ejemplo: registra solicitudes de cumplimiento, permite consultarlas y tomar una decisión. Funciona y está probada, pero vive en un único módulo.

Abrir práctica extendida: base común y 1 parte

Base común

  • El starter arranca y sus tests deben estar verdes antes de editar.
  • El contrato público y los datos sintéticos son distintos al ejercicio guiado.
  • Cada parte declara qué mecanismo puede añadirse; persistencia, autenticación, servicios y auto-registro siguen fuera.
  • Los criterios dicen qué conservar, no qué carpetas debes crear.

Paquete de trabajo

Entorno, evidencia y reinicio

Entorno: Python 3.10+ en un workspace temporal; FastAPI, Pydantic 2, pytest y httpx2 instalados por el paquete con uv.

  • Commit o diff del refactor sin cambios funcionales.
  • Salida completa de pytest antes y después.
  • Fingerprint OpenAPI y diagrama de imports final.

Revisión: con Codex, utilizando los artefactos y criterios de cada parte; no se publica una solución oficial.

Reinicio: Descomprimir de nuevo el starter en otro directorio temporal; cada intento empieza con el monolito y sus tests verdes.

Parte 2 · Apoyo autónomo

EX-B3-S01-02 · Proporcionar contexto, settings y auditoría

Reemplazar repetición de frontera, constantes de entorno y cleanup manual por proveedores explícitos, conservando el contrato y demostrando cada alcance.

Qué debes hacer
  1. Documenta el árbol deseado y clasifica cada nodo como petición, proceso o recurso antes de editar.
  2. Conserva el contrato de headers, query, respuestas y OpenAPI mientras eliminas la repetición de contexto.
  3. Recibe configuración tipada desde fuentes externas y permite sustituir su proveedor en tests.
  4. Gestiona el audit sink mediante un ciclo con yield y prueba cierre en éxito y error.
  5. Entrega una matriz que conecte cada decisión con una prueba o traza observable.
Entrega esperada
  • Repositorio refactorizado sin persistencia, seguridad ni funcionalidad nueva.
  • Tests propios de caché por petición, settings/override y lifecycle.
  • before-after.md con árbol, comandos, resultados, decisiones y límite de parada.
Criterios de aceptación
  • Los ocho tests suministrados pasan antes y después y el fingerprint de operaciones y parámetros OpenAPI no cambia.
  • La subdependencia común se ejecuta una vez por petición y vuelve a ejecutarse en otra petición.
  • Settings usa pydantic-settings, prefijo explícito y un campo obligatorio que falla al faltar; ningún valor sensible se publica.
  • El test sustituye el proveedor de settings y restaura overrides y cachés controladas.
  • El audit sink se abre y cierra una vez en éxito y error mediante una dependencia con yield, sin ocultar la excepción.
  • No hay recurso global mutable, service locator, use_cache=False sin necesidad ni imports de vuelta hacia main.py.
  • La entrega explica por qué cada alcance es suficiente y dónde se detuvo la composición.
Evidencia para revisión
  • Árbol y clasificación petición/proceso/recurso antes del cambio.
  • Diff, tests añadidos y misma regresión HTTP/OpenAPI después del refactor.
  • Trazas de caché y cleanup junto con un override de settings restaurado.

Reinicio de esta parte: Volver a descomprimir el checkpoint; eliminar el .env local del intento y no reutilizar código de los ensayos guiados.

Transferencia: Ante una sesión, un cliente HTTP o un usuario actual, puedes decidir qué debe vivir por petición, por proceso o fuera de Depends y cómo probarlo.