Spaces:
Sleeping
Sleeping
coder16 commited on
Commit ·
57090be
1
Parent(s): 67aa1ca
update
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- README.md +79 -0
- app/__pycache__/__init__.cpython-314.pyc +0 -0
- app/__pycache__/main.cpython-314.pyc +0 -0
- app/core/__pycache__/__init__.cpython-314.pyc +0 -0
- app/core/__pycache__/app.cpython-314.pyc +0 -0
- app/core/__pycache__/config.cpython-314.pyc +0 -0
- app/core/__pycache__/exception_handlers.cpython-314.pyc +0 -0
- app/core/__pycache__/lifespan.cpython-314.pyc +0 -0
- app/core/__pycache__/middleware.cpython-314.pyc +0 -0
- app/core/__pycache__/security.cpython-314.pyc +0 -0
- app/core/app.py +13 -1
- app/core/config.py +2 -0
- app/core/lifespan.py +17 -3
- app/database/__pycache__/__init__.cpython-314.pyc +0 -0
- app/database/__pycache__/collections.cpython-314.pyc +0 -0
- app/database/__pycache__/indexes.cpython-314.pyc +0 -0
- app/database/__pycache__/mongodb.cpython-314.pyc +0 -0
- app/database/__pycache__/objectid.cpython-314.pyc +0 -0
- app/database/mongodb.py +62 -8
- app/exceptions/__pycache__/__init__.cpython-314.pyc +0 -0
- app/exceptions/__pycache__/base.cpython-314.pyc +0 -0
- app/models/__pycache__/__init__.cpython-314.pyc +0 -0
- app/models/__pycache__/categoria.cpython-314.pyc +0 -0
- app/models/__pycache__/common.cpython-314.pyc +0 -0
- app/models/__pycache__/item.cpython-314.pyc +0 -0
- app/models/__pycache__/negocio.cpython-314.pyc +0 -0
- app/models/__pycache__/resena.cpython-314.pyc +0 -0
- app/models/__pycache__/user.cpython-314.pyc +0 -0
- app/rutas/__pycache__/__init__.cpython-314.pyc +0 -0
- app/rutas/__pycache__/auth.cpython-314.pyc +0 -0
- app/rutas/__pycache__/categorias.cpython-314.pyc +0 -0
- app/rutas/__pycache__/deps.cpython-314.pyc +0 -0
- app/rutas/__pycache__/items.cpython-314.pyc +0 -0
- app/rutas/__pycache__/negocios.cpython-314.pyc +0 -0
- app/rutas/__pycache__/resenas.cpython-314.pyc +0 -0
- app/schemas/__pycache__/__init__.cpython-314.pyc +0 -0
- app/schemas/__pycache__/auth.cpython-314.pyc +0 -0
- app/schemas/__pycache__/categoria.cpython-314.pyc +0 -0
- app/schemas/__pycache__/common.cpython-314.pyc +0 -0
- app/schemas/__pycache__/item.cpython-314.pyc +0 -0
- app/schemas/__pycache__/negocio.cpython-314.pyc +0 -0
- app/schemas/__pycache__/resena.cpython-314.pyc +0 -0
- app/services/__pycache__/__init__.cpython-314.pyc +0 -0
- app/services/__pycache__/auth.cpython-314.pyc +0 -0
- app/services/__pycache__/base.cpython-314.pyc +0 -0
- app/services/__pycache__/categoria.cpython-314.pyc +0 -0
- app/services/__pycache__/item.cpython-314.pyc +0 -0
- app/services/__pycache__/negocio.cpython-314.pyc +0 -0
- app/services/__pycache__/resena.cpython-314.pyc +0 -0
- app/services/__pycache__/utils.cpython-314.pyc +0 -0
README.md
CHANGED
|
@@ -51,6 +51,85 @@ app/
|
|
| 51 |
└── main.py Punto de entrada (crea la app).
|
| 52 |
```
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
La API quedará disponible en `http://localhost:7860` (Swagger en `/docs`).
|
| 55 |
|
| 56 |
## Despliegue en HuggingFace Spaces (Docker)
|
|
|
|
| 51 |
└── main.py Punto de entrada (crea la app).
|
| 52 |
```
|
| 53 |
|
| 54 |
+
### Cómo extender
|
| 55 |
+
|
| 56 |
+
Añadir una nueva entidad es directo gracias al `BaseService`
|
| 57 |
+
(`app/services/base.py`), que implementa el CRUD genérico:
|
| 58 |
+
|
| 59 |
+
1. Define el modelo en `models/` y los esquemas en `schemas/`.
|
| 60 |
+
2. Crea un servicio que herede de `BaseService` (fija `collection_name`).
|
| 61 |
+
3. Añade el router en `rutas/` e inclúyelo en `rutas/__init__.py`.
|
| 62 |
+
4. (Opcional) Declara índices en `database/indexes.py`.
|
| 63 |
+
|
| 64 |
+
## Requisitos
|
| 65 |
+
|
| 66 |
+
- Python 3.11+
|
| 67 |
+
- MongoDB 4.4+ en ejecución (local o remoto)
|
| 68 |
+
|
| 69 |
+
## Instalación
|
| 70 |
+
|
| 71 |
+
```bash
|
| 72 |
+
python -m venv .venv
|
| 73 |
+
source .venv/bin/activate # En Windows: .venv\Scripts\activate
|
| 74 |
+
pip install -r requirements.txt
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
## Configuración
|
| 78 |
+
|
| 79 |
+
Copia `.env.example` a `.env` y ajusta los valores:
|
| 80 |
+
|
| 81 |
+
```bash
|
| 82 |
+
cp .env.example .env
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
Genera una clave secreta segura para `SECRET_KEY`:
|
| 86 |
+
|
| 87 |
+
```bash
|
| 88 |
+
python -c "import secrets; print(secrets.token_urlsafe(48))"
|
| 89 |
+
```
|
| 90 |
+
|
| 91 |
+
| Variable | Descripción | Por defecto |
|
| 92 |
+
|-------------------------------|-----------------------------------------------|-----------------------------|
|
| 93 |
+
| `APP_NAME` | Nombre de la aplicación | `Directorio Online API` |
|
| 94 |
+
| `APP_VERSION` | Versión | `1.0.0` |
|
| 95 |
+
| `APP_DESCRIPTION` | Descripción de la API | (ver `.env.example`) |
|
| 96 |
+
| `DEBUG` | Modo depuración | `false` |
|
| 97 |
+
| `API_PREFIX` | Prefijo de las rutas | `/api/v1` |
|
| 98 |
+
| `PORT` | Puerto de escucha del contenedor | `7860` |
|
| 99 |
+
| `MONGODB_URI` | URI de conexión a MongoDB | `mongodb://localhost:27017` |
|
| 100 |
+
| `MONGODB_DB_NAME` | Nombre de la base de datos | `directorio_online` |
|
| 101 |
+
| `SECRET_KEY` | Clave para firmar los JWT (**obligatoria**) | — |
|
| 102 |
+
| `ALGORITHM` | Algoritmo de firma del JWT | `HS256` |
|
| 103 |
+
| `ACCESS_TOKEN_EXPIRE_MINUTES` | Validez del token de acceso (minutos) | `60` |
|
| 104 |
+
| `CORS_ORIGINS` | Orígenes permitidos (lista por comas o `*`) | `*` |
|
| 105 |
+
|
| 106 |
+
## Ejecución
|
| 107 |
+
|
| 108 |
+
```bash
|
| 109 |
+
uvicorn app.main:app --reload
|
| 110 |
+
```
|
| 111 |
+
|
| 112 |
+
- Documentación interactiva (Swagger): `http://localhost:8000/docs`
|
| 113 |
+
- Documentación alternativa (ReDoc): `http://localhost:8000/redoc`
|
| 114 |
+
- Comprobación de salud: `http://localhost:8000/health`
|
| 115 |
+
|
| 116 |
+
## Docker
|
| 117 |
+
|
| 118 |
+
La aplicación se empaqueta con el `Dockerfile` incluido. El contenedor
|
| 119 |
+
escucha en el puerto indicado por la variable `PORT` (por defecto `7860`).
|
| 120 |
+
|
| 121 |
+
```bash
|
| 122 |
+
# Construir la imagen
|
| 123 |
+
docker build -t directorio-online-backend .
|
| 124 |
+
|
| 125 |
+
# Ejecutar (las variables se pasan con -e o con --env-file)
|
| 126 |
+
docker run --rm -p 7860:7860 \
|
| 127 |
+
-e SECRET_KEY="$(python -c 'import secrets; print(secrets.token_urlsafe(48))')" \
|
| 128 |
+
-e MONGODB_URI="mongodb+srv://usuario:password@cluster.mongodb.net" \
|
| 129 |
+
-e MONGODB_DB_NAME="directorio_online" \
|
| 130 |
+
directorio-online-backend
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
La API quedará disponible en `http://localhost:7860` (Swagger en `/docs`).
|
| 134 |
|
| 135 |
## Despliegue en HuggingFace Spaces (Docker)
|
app/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (436 Bytes). View file
|
|
|
app/__pycache__/main.cpython-314.pyc
ADDED
|
Binary file (369 Bytes). View file
|
|
|
app/core/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (321 Bytes). View file
|
|
|
app/core/__pycache__/app.cpython-314.pyc
ADDED
|
Binary file (2.71 kB). View file
|
|
|
app/core/__pycache__/config.cpython-314.pyc
ADDED
|
Binary file (3.19 kB). View file
|
|
|
app/core/__pycache__/exception_handlers.cpython-314.pyc
ADDED
|
Binary file (2.51 kB). View file
|
|
|
app/core/__pycache__/lifespan.cpython-314.pyc
ADDED
|
Binary file (2.3 kB). View file
|
|
|
app/core/__pycache__/middleware.cpython-314.pyc
ADDED
|
Binary file (1.08 kB). View file
|
|
|
app/core/__pycache__/security.cpython-314.pyc
ADDED
|
Binary file (6.41 kB). View file
|
|
|
app/core/app.py
CHANGED
|
@@ -27,7 +27,19 @@ def create_app() -> FastAPI:
|
|
| 27 |
|
| 28 |
@app.get("/health", tags=["Salud"], summary="Estado del servicio")
|
| 29 |
async def health() -> dict[str, str]:
|
| 30 |
-
"""
|
| 31 |
return {"status": "ok"}
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
return app
|
|
|
|
| 27 |
|
| 28 |
@app.get("/health", tags=["Salud"], summary="Estado del servicio")
|
| 29 |
async def health() -> dict[str, str]:
|
| 30 |
+
"""Liveness: responde siempre y rápido (no depende de la base de datos)."""
|
| 31 |
return {"status": "ok"}
|
| 32 |
|
| 33 |
+
@app.get(
|
| 34 |
+
"/health/db",
|
| 35 |
+
tags=["Salud"],
|
| 36 |
+
summary="Estado de la conexión a MongoDB",
|
| 37 |
+
)
|
| 38 |
+
async def health_db() -> dict[str, str]:
|
| 39 |
+
"""Readiness: comprueba si MongoDB responde en este momento."""
|
| 40 |
+
from app.database.mongodb import mongodb
|
| 41 |
+
|
| 42 |
+
conectado = await mongodb.ping()
|
| 43 |
+
return {"database": "connected" if conectado else "disconnected"}
|
| 44 |
+
|
| 45 |
return app
|
app/core/config.py
CHANGED
|
@@ -32,6 +32,8 @@ class Settings(BaseSettings):
|
|
| 32 |
# --- Base de datos (MongoDB) ---
|
| 33 |
MONGODB_URI: str = "mongodb://localhost:27017"
|
| 34 |
MONGODB_DB_NAME: str = "directorio_online"
|
|
|
|
|
|
|
| 35 |
|
| 36 |
# --- Seguridad / JWT ---
|
| 37 |
SECRET_KEY: str
|
|
|
|
| 32 |
# --- Base de datos (MongoDB) ---
|
| 33 |
MONGODB_URI: str = "mongodb://localhost:27017"
|
| 34 |
MONGODB_DB_NAME: str = "directorio_online"
|
| 35 |
+
# Tiempo máximo (ms) para seleccionar un servidor de MongoDB.
|
| 36 |
+
MONGODB_TIMEOUT_MS: int = 5000
|
| 37 |
|
| 38 |
# --- Seguridad / JWT ---
|
| 39 |
SECRET_KEY: str
|
app/core/lifespan.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
| 1 |
"""Ciclo de vida de la aplicación.
|
| 2 |
|
| 3 |
-
|
| 4 |
-
|
|
|
|
| 5 |
"""
|
| 6 |
|
| 7 |
from __future__ import annotations
|
| 8 |
|
|
|
|
| 9 |
from contextlib import asynccontextmanager
|
| 10 |
from typing import AsyncIterator
|
| 11 |
|
|
@@ -14,12 +16,24 @@ from fastapi import FastAPI
|
|
| 14 |
from app.database.indexes import ensure_indexes
|
| 15 |
from app.database.mongodb import mongodb
|
| 16 |
|
|
|
|
|
|
|
| 17 |
|
| 18 |
@asynccontextmanager
|
| 19 |
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
| 20 |
"""Gestiona los recursos de la aplicación durante su ciclo de vida."""
|
| 21 |
await mongodb.connect()
|
| 22 |
-
await
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
try:
|
| 24 |
yield
|
| 25 |
finally:
|
|
|
|
| 1 |
"""Ciclo de vida de la aplicación.
|
| 2 |
|
| 3 |
+
Crea el cliente de MongoDB y, si responde, asegura los índices. Si la base
|
| 4 |
+
de datos no está disponible al arrancar, la aplicación arranca igualmente
|
| 5 |
+
(no se cae) y la conexión se reintentará en cada petición.
|
| 6 |
"""
|
| 7 |
|
| 8 |
from __future__ import annotations
|
| 9 |
|
| 10 |
+
import logging
|
| 11 |
from contextlib import asynccontextmanager
|
| 12 |
from typing import AsyncIterator
|
| 13 |
|
|
|
|
| 16 |
from app.database.indexes import ensure_indexes
|
| 17 |
from app.database.mongodb import mongodb
|
| 18 |
|
| 19 |
+
logger = logging.getLogger(__name__)
|
| 20 |
+
|
| 21 |
|
| 22 |
@asynccontextmanager
|
| 23 |
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
| 24 |
"""Gestiona los recursos de la aplicación durante su ciclo de vida."""
|
| 25 |
await mongodb.connect()
|
| 26 |
+
if await mongodb.ping():
|
| 27 |
+
try:
|
| 28 |
+
await ensure_indexes()
|
| 29 |
+
except Exception as exc: # noqa: BLE001
|
| 30 |
+
logger.warning("No se pudieron crear los índices: %s", exc)
|
| 31 |
+
else:
|
| 32 |
+
logger.warning(
|
| 33 |
+
"La aplicación arranca SIN conexión a MongoDB. Se reintentará "
|
| 34 |
+
"en cada petición. Revisa MONGODB_URI y el IP Access List de "
|
| 35 |
+
"Atlas (debe incluir 0.0.0.0/0 para hosts en la nube)."
|
| 36 |
+
)
|
| 37 |
try:
|
| 38 |
yield
|
| 39 |
finally:
|
app/database/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (472 Bytes). View file
|
|
|
app/database/__pycache__/collections.cpython-314.pyc
ADDED
|
Binary file (510 Bytes). View file
|
|
|
app/database/__pycache__/indexes.cpython-314.pyc
ADDED
|
Binary file (3.04 kB). View file
|
|
|
app/database/__pycache__/mongodb.cpython-314.pyc
ADDED
|
Binary file (6.74 kB). View file
|
|
|
app/database/__pycache__/objectid.cpython-314.pyc
ADDED
|
Binary file (1.31 kB). View file
|
|
|
app/database/mongodb.py
CHANGED
|
@@ -3,11 +3,16 @@
|
|
| 3 |
Se utiliza el driver oficial ``pymongo`` con su API asíncrona
|
| 4 |
(:class:`pymongo.AsyncMongoClient`), disponible de forma estable a
|
| 5 |
partir de PyMongo 4.13.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
"""
|
| 7 |
|
| 8 |
from __future__ import annotations
|
| 9 |
|
| 10 |
import logging
|
|
|
|
| 11 |
|
| 12 |
from pymongo import AsyncMongoClient
|
| 13 |
from pymongo.asynchronous.collection import AsyncCollection
|
|
@@ -22,23 +27,72 @@ class MongoDB:
|
|
| 22 |
"""Contenedor del cliente y la base de datos de MongoDB.
|
| 23 |
|
| 24 |
Mantiene una única instancia del cliente durante el ciclo de vida de
|
| 25 |
-
la aplicación.
|
| 26 |
-
apagar el servidor.
|
| 27 |
"""
|
| 28 |
|
| 29 |
client: AsyncMongoClient | None = None
|
| 30 |
database: AsyncDatabase | None = None
|
| 31 |
|
| 32 |
async def connect(self) -> None:
|
| 33 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
if self.client is not None:
|
| 35 |
return
|
| 36 |
-
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
| 38 |
self.database = self.client[settings.MONGODB_DB_NAME]
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
async def close(self) -> None:
|
| 44 |
"""Cierra la conexión con MongoDB."""
|
|
|
|
| 3 |
Se utiliza el driver oficial ``pymongo`` con su API asíncrona
|
| 4 |
(:class:`pymongo.AsyncMongoClient`), disponible de forma estable a
|
| 5 |
partir de PyMongo 4.13.
|
| 6 |
+
|
| 7 |
+
El cliente se crea de forma perezosa: la conexión real se abre en la
|
| 8 |
+
primera operación, por lo que la aplicación puede arrancar aunque la
|
| 9 |
+
base de datos no esté disponible todavía (no se bloquea el arranque).
|
| 10 |
"""
|
| 11 |
|
| 12 |
from __future__ import annotations
|
| 13 |
|
| 14 |
import logging
|
| 15 |
+
import socket
|
| 16 |
|
| 17 |
from pymongo import AsyncMongoClient
|
| 18 |
from pymongo.asynchronous.collection import AsyncCollection
|
|
|
|
| 27 |
"""Contenedor del cliente y la base de datos de MongoDB.
|
| 28 |
|
| 29 |
Mantiene una única instancia del cliente durante el ciclo de vida de
|
| 30 |
+
la aplicación.
|
|
|
|
| 31 |
"""
|
| 32 |
|
| 33 |
client: AsyncMongoClient | None = None
|
| 34 |
database: AsyncDatabase | None = None
|
| 35 |
|
| 36 |
async def connect(self) -> None:
|
| 37 |
+
"""Crea el cliente de MongoDB sin bloquear el arranque.
|
| 38 |
+
|
| 39 |
+
No se hace ``ping`` aquí a propósito: el cliente es perezoso y la
|
| 40 |
+
conexión se abre en la primera operación. Así la app arranca aunque
|
| 41 |
+
Mongo no responda todavía.
|
| 42 |
+
"""
|
| 43 |
if self.client is not None:
|
| 44 |
return
|
| 45 |
+
self.client = AsyncMongoClient(
|
| 46 |
+
settings.MONGODB_URI,
|
| 47 |
+
tz_aware=True,
|
| 48 |
+
serverSelectionTimeoutMS=settings.MONGODB_TIMEOUT_MS,
|
| 49 |
+
)
|
| 50 |
self.database = self.client[settings.MONGODB_DB_NAME]
|
| 51 |
+
|
| 52 |
+
async def ping(self) -> bool:
|
| 53 |
+
"""Comprueba si MongoDB responde. No lanza excepción."""
|
| 54 |
+
if self.client is None:
|
| 55 |
+
return False
|
| 56 |
+
try:
|
| 57 |
+
await self.client.admin.command("ping")
|
| 58 |
+
except Exception as exc: # noqa: BLE001
|
| 59 |
+
logger.warning("MongoDB no responde: %s", exc)
|
| 60 |
+
self._diagnostico_red()
|
| 61 |
+
return False
|
| 62 |
+
logger.info("MongoDB conectado (db=%s).", settings.MONGODB_DB_NAME)
|
| 63 |
+
return True
|
| 64 |
+
|
| 65 |
+
def _diagnostico_red(self) -> None:
|
| 66 |
+
"""Registra un diagnóstico de red hacia los nodos de MongoDB.
|
| 67 |
+
|
| 68 |
+
Resuelve el DNS y prueba un socket TCP crudo a cada nodo para
|
| 69 |
+
distinguir un bloqueo de red de un problema del driver/credenciales.
|
| 70 |
+
"""
|
| 71 |
+
try:
|
| 72 |
+
nodos = self.client.topology_description.server_descriptions()
|
| 73 |
+
except Exception: # noqa: BLE001
|
| 74 |
+
return
|
| 75 |
+
for host, port in nodos:
|
| 76 |
+
try:
|
| 77 |
+
ip = socket.gethostbyname(host)
|
| 78 |
+
except OSError as exc:
|
| 79 |
+
logger.warning("DIAG DNS %s -> FALLA (%s)", host, exc)
|
| 80 |
+
continue
|
| 81 |
+
sock = socket.socket()
|
| 82 |
+
sock.settimeout(5)
|
| 83 |
+
try:
|
| 84 |
+
sock.connect((host, port))
|
| 85 |
+
logger.warning("DIAG TCP %s:%s (%s) -> OK", host, port, ip)
|
| 86 |
+
except OSError as exc:
|
| 87 |
+
logger.warning(
|
| 88 |
+
"DIAG TCP %s:%s (%s) -> BLOQUEADO/timeout (%s)",
|
| 89 |
+
host,
|
| 90 |
+
port,
|
| 91 |
+
ip,
|
| 92 |
+
type(exc).__name__,
|
| 93 |
+
)
|
| 94 |
+
finally:
|
| 95 |
+
sock.close()
|
| 96 |
|
| 97 |
async def close(self) -> None:
|
| 98 |
"""Cierra la conexión con MongoDB."""
|
app/exceptions/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (495 Bytes). View file
|
|
|
app/exceptions/__pycache__/base.cpython-314.pyc
ADDED
|
Binary file (3.17 kB). View file
|
|
|
app/models/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (932 Bytes). View file
|
|
|
app/models/__pycache__/categoria.cpython-314.pyc
ADDED
|
Binary file (938 Bytes). View file
|
|
|
app/models/__pycache__/common.cpython-314.pyc
ADDED
|
Binary file (5.74 kB). View file
|
|
|
app/models/__pycache__/item.cpython-314.pyc
ADDED
|
Binary file (1.21 kB). View file
|
|
|
app/models/__pycache__/negocio.cpython-314.pyc
ADDED
|
Binary file (1.74 kB). View file
|
|
|
app/models/__pycache__/resena.cpython-314.pyc
ADDED
|
Binary file (1.08 kB). View file
|
|
|
app/models/__pycache__/user.cpython-314.pyc
ADDED
|
Binary file (1.16 kB). View file
|
|
|
app/rutas/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (852 Bytes). View file
|
|
|
app/rutas/__pycache__/auth.cpython-314.pyc
ADDED
|
Binary file (3.02 kB). View file
|
|
|
app/rutas/__pycache__/categorias.cpython-314.pyc
ADDED
|
Binary file (4.26 kB). View file
|
|
|
app/rutas/__pycache__/deps.cpython-314.pyc
ADDED
|
Binary file (4.42 kB). View file
|
|
|
app/rutas/__pycache__/items.cpython-314.pyc
ADDED
|
Binary file (4.22 kB). View file
|
|
|
app/rutas/__pycache__/negocios.cpython-314.pyc
ADDED
|
Binary file (4.3 kB). View file
|
|
|
app/rutas/__pycache__/resenas.cpython-314.pyc
ADDED
|
Binary file (4.16 kB). View file
|
|
|
app/schemas/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (1.06 kB). View file
|
|
|
app/schemas/__pycache__/auth.cpython-314.pyc
ADDED
|
Binary file (2.58 kB). View file
|
|
|
app/schemas/__pycache__/categoria.cpython-314.pyc
ADDED
|
Binary file (1.78 kB). View file
|
|
|
app/schemas/__pycache__/common.cpython-314.pyc
ADDED
|
Binary file (1.15 kB). View file
|
|
|
app/schemas/__pycache__/item.cpython-314.pyc
ADDED
|
Binary file (2.16 kB). View file
|
|
|
app/schemas/__pycache__/negocio.cpython-314.pyc
ADDED
|
Binary file (2.83 kB). View file
|
|
|
app/schemas/__pycache__/resena.cpython-314.pyc
ADDED
|
Binary file (1.83 kB). View file
|
|
|
app/services/__pycache__/__init__.cpython-314.pyc
ADDED
|
Binary file (582 Bytes). View file
|
|
|
app/services/__pycache__/auth.cpython-314.pyc
ADDED
|
Binary file (3.56 kB). View file
|
|
|
app/services/__pycache__/base.cpython-314.pyc
ADDED
|
Binary file (6.83 kB). View file
|
|
|
app/services/__pycache__/categoria.cpython-314.pyc
ADDED
|
Binary file (6.79 kB). View file
|
|
|
app/services/__pycache__/item.cpython-314.pyc
ADDED
|
Binary file (4.6 kB). View file
|
|
|
app/services/__pycache__/negocio.cpython-314.pyc
ADDED
|
Binary file (6.07 kB). View file
|
|
|
app/services/__pycache__/resena.cpython-314.pyc
ADDED
|
Binary file (4.48 kB). View file
|
|
|
app/services/__pycache__/utils.cpython-314.pyc
ADDED
|
Binary file (1.26 kB). View file
|
|
|