calypso-api 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. calypso_api-0.1.0/.python-version +1 -0
  2. calypso_api-0.1.0/Dockerfile +13 -0
  3. calypso_api-0.1.0/PKG-INFO +81 -0
  4. calypso_api-0.1.0/README.md +56 -0
  5. calypso_api-0.1.0/docker-compose.yml +27 -0
  6. calypso_api-0.1.0/main.py +102 -0
  7. calypso_api-0.1.0/pyproject.toml +42 -0
  8. calypso_api-0.1.0/requirements.txt +12 -0
  9. calypso_api-0.1.0/src/calypso_api/__init__.py +0 -0
  10. calypso_api-0.1.0/src/calypso_api/__main__.py +4 -0
  11. calypso_api-0.1.0/src/calypso_api/auth/__init__.py +0 -0
  12. calypso_api-0.1.0/src/calypso_api/cli.py +44 -0
  13. calypso_api-0.1.0/src/calypso_api/controllers/__init__.py +0 -0
  14. calypso_api-0.1.0/src/calypso_api/core/__init__.py +0 -0
  15. calypso_api-0.1.0/src/calypso_api/core/config.py +23 -0
  16. calypso_api-0.1.0/src/calypso_api/database/__init__.py +0 -0
  17. calypso_api-0.1.0/src/calypso_api/database/db.py +24 -0
  18. calypso_api-0.1.0/src/calypso_api/dependencies/__init__.py +0 -0
  19. calypso_api-0.1.0/src/calypso_api/helpers/__init__.py +0 -0
  20. calypso_api-0.1.0/src/calypso_api/main.py +38 -0
  21. calypso_api-0.1.0/src/calypso_api/models/__init__.py +0 -0
  22. calypso_api-0.1.0/src/calypso_api/repositories/__init__.py +0 -0
  23. calypso_api-0.1.0/src/calypso_api/routes/__init__.py +0 -0
  24. calypso_api-0.1.0/src/calypso_api/routes/health.py +8 -0
  25. calypso_api-0.1.0/src/calypso_api/scaffold.py +931 -0
  26. calypso_api-0.1.0/src/calypso_api/schemas/__init__.py +0 -0
  27. calypso_api-0.1.0/src/calypso_api/services/__init__.py +0 -0
  28. calypso_api-0.1.0/src/calypso_api/test/__init__.py +0 -0
  29. calypso_api-0.1.0/src/calypso_api/utils/__init__.py +0 -0
  30. calypso_api-0.1.0/uv.lock +1010 -0
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,13 @@
1
+
2
+ FROM python:3.11-slim
3
+
4
+ WORKDIR /app
5
+
6
+ RUN apt-get update && apt-get install -y --no-install-recommends build-essential libpq-dev && rm -rf /var/lib/apt/lists/*
7
+
8
+ COPY requirements.txt .
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ COPY . .
12
+
13
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.4
2
+ Name: calypso-api
3
+ Version: 0.1.0
4
+ Summary: Calypso API Library and CLI for scaffolding FastAPI projects
5
+ Author-email: Juan Maniglia <juan.maniglia@example.com>
6
+ License: MIT
7
+ Classifier: Framework :: FastAPI
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Python: >=3.12
12
+ Requires-Dist: aiosqlite>=0.22.1
13
+ Requires-Dist: asyncpg>=0.31.0
14
+ Requires-Dist: bcrypt>=5.0.0
15
+ Requires-Dist: fastapi>=0.128.0
16
+ Requires-Dist: python-dotenv>=1.2.1
17
+ Requires-Dist: python-jose[cryptography]>=3.5.0
18
+ Requires-Dist: python-multipart>=0.0.22
19
+ Requires-Dist: slowapi>=0.1.9
20
+ Requires-Dist: sqlalchemy>=2.0.46
21
+ Requires-Dist: sqlmodel>=0.0.32
22
+ Requires-Dist: typer>=0.21.1
23
+ Requires-Dist: uvicorn>=0.40.0
24
+ Description-Content-Type: text/markdown
25
+
26
+ # Calypso API
27
+
28
+ Librería y CLI para crear estructuras de proyectos robustos y escalables con FastAPI, SQLAlchemy (Async) y PostgreSQL.
29
+
30
+ ## Instalación
31
+
32
+ Puedes instalar `calypso-api` directamente desde PyPI usando `pip` o `uv`:
33
+
34
+ ```bash
35
+ uv add calypso-api
36
+ # O con pip
37
+ pip install calypso-api
38
+ ```
39
+
40
+ ## Uso
41
+
42
+ Una vez instalado, tendrás acceso al comando `calypso` en tu terminal.
43
+
44
+ ### Crear un nuevo proyecto
45
+
46
+ Para generar un nuevo proyecto con toda la estructura lista:
47
+
48
+ ```bash
49
+ calypso init mi_nuevo_proyecto "Mi Nuevo Proyecto" --host 0.0.0.0 --port 8000 --docker
50
+ ```
51
+
52
+ Esto creará una carpeta `mi_nuevo_proyecto` con:
53
+ - Estructura modular (Controllers, Models, Routes, etc.)
54
+ - Configuración de Docker y Docker Compose.
55
+ - Autenticación JWT configurada.
56
+ - Documentación automática lista.
57
+
58
+ ### Comandos disponibles
59
+
60
+ ```bash
61
+ # Inicializar un proyecto
62
+ calypso init <directorio> <nombre_proyecto>
63
+
64
+ # Ver ayuda
65
+ calypso --help
66
+ ```
67
+
68
+ ## Estructura Generada
69
+
70
+ El proyecto generado tendrá la siguiente estructura:
71
+
72
+ - `auth/`: Lógica de autenticación.
73
+ - `controllers/`: Controladores de la lógica de negocio.
74
+ - `core/`: Configuración global.
75
+ - `database/`: Configuración de base de datos.
76
+ - `routes/`: Definición de endpoints.
77
+ - `models/`: Modelos de base de datos.
78
+ - `schemas/`: Schemas Pydantic.
79
+ - `helpers/`: Utilidades generales.
80
+ - `services/`: Lógica de negocio compleja.
81
+ - `docker-compose.yml`: Orquestación de contenedores.
@@ -0,0 +1,56 @@
1
+ # Calypso API
2
+
3
+ Librería y CLI para crear estructuras de proyectos robustos y escalables con FastAPI, SQLAlchemy (Async) y PostgreSQL.
4
+
5
+ ## Instalación
6
+
7
+ Puedes instalar `calypso-api` directamente desde PyPI usando `pip` o `uv`:
8
+
9
+ ```bash
10
+ uv add calypso-api
11
+ # O con pip
12
+ pip install calypso-api
13
+ ```
14
+
15
+ ## Uso
16
+
17
+ Una vez instalado, tendrás acceso al comando `calypso` en tu terminal.
18
+
19
+ ### Crear un nuevo proyecto
20
+
21
+ Para generar un nuevo proyecto con toda la estructura lista:
22
+
23
+ ```bash
24
+ calypso init mi_nuevo_proyecto "Mi Nuevo Proyecto" --host 0.0.0.0 --port 8000 --docker
25
+ ```
26
+
27
+ Esto creará una carpeta `mi_nuevo_proyecto` con:
28
+ - Estructura modular (Controllers, Models, Routes, etc.)
29
+ - Configuración de Docker y Docker Compose.
30
+ - Autenticación JWT configurada.
31
+ - Documentación automática lista.
32
+
33
+ ### Comandos disponibles
34
+
35
+ ```bash
36
+ # Inicializar un proyecto
37
+ calypso init <directorio> <nombre_proyecto>
38
+
39
+ # Ver ayuda
40
+ calypso --help
41
+ ```
42
+
43
+ ## Estructura Generada
44
+
45
+ El proyecto generado tendrá la siguiente estructura:
46
+
47
+ - `auth/`: Lógica de autenticación.
48
+ - `controllers/`: Controladores de la lógica de negocio.
49
+ - `core/`: Configuración global.
50
+ - `database/`: Configuración de base de datos.
51
+ - `routes/`: Definición de endpoints.
52
+ - `models/`: Modelos de base de datos.
53
+ - `schemas/`: Schemas Pydantic.
54
+ - `helpers/`: Utilidades generales.
55
+ - `services/`: Lógica de negocio compleja.
56
+ - `docker-compose.yml`: Orquestación de contenedores.
@@ -0,0 +1,27 @@
1
+
2
+ services:
3
+ api:
4
+ build: .
5
+ ports:
6
+ - "8000:8000"
7
+ environment:
8
+ - POSTGRES_SERVER=db
9
+ - POSTGRES_USER=postgres
10
+ - POSTGRES_PASSWORD=postgres
11
+ - POSTGRES_DB=app
12
+ depends_on:
13
+ - db
14
+
15
+ db:
16
+ image: postgres:15-alpine
17
+ environment:
18
+ - POSTGRES_USER=postgres
19
+ - POSTGRES_PASSWORD=postgres
20
+ - POSTGRES_DB=app
21
+ volumes:
22
+ - postgres_data:/var/lib/postgresql/data
23
+ ports:
24
+ - "5432:5432"
25
+
26
+ volumes:
27
+ postgres_data:
@@ -0,0 +1,102 @@
1
+ from fastapi import FastAPI, Request, HTTPException
2
+ from fastapi.staticfiles import StaticFiles
3
+ from starlette.middleware.cors import CORSMiddleware
4
+ from starlette.middleware.gzip import GZipMiddleware
5
+ from fastapi.responses import JSONResponse, FileResponse
6
+ from slowapi import _rate_limit_exceeded_handler
7
+ from slowapi.errors import RateLimitExceeded
8
+ from dependencies.limitador import limiter
9
+ from database.db_service import create_db_and_tables
10
+ from core import config
11
+ from contextlib import asynccontextmanager
12
+ from database.db import session_manager
13
+ from core.exceptions import exception_handler, http_exception_handler
14
+ from utils.logger import configure_logger
15
+ from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html
16
+
17
+ # Routers
18
+ from auth.auth_routes import router as security_router
19
+ from routes.example_router import router as example_router
20
+
21
+ description = f"""
22
+ # {config.PROJECT_NAME}
23
+
24
+ *{config.PROJECT_DESCRIPTION}*
25
+ """
26
+
27
+ logger = configure_logger(name=__name__)
28
+
29
+ @asynccontextmanager
30
+ async def lifespan(app: FastAPI):
31
+ """
32
+ Función que maneja los eventos de inicio y cierre de la aplicación.
33
+ """
34
+ if config.crear_usuarios_y_tablas:
35
+ await create_db_and_tables()
36
+
37
+ from utils.defaultUser import create_defaultAdmin_user
38
+ from database.db_service import get_session_context
39
+ async for session in get_session_context():
40
+ await create_defaultAdmin_user(db=session)
41
+ break
42
+
43
+ yield
44
+
45
+ if session_manager._engine is not None:
46
+ await session_manager.close()
47
+ logger.info("Conexión a la base de datos cerrada.")
48
+
49
+ app = FastAPI(
50
+ title=config.PROJECT_NAME,
51
+ description=description,
52
+ version=config.VERSION,
53
+ debug=config.DEBUG,
54
+ lifespan=lifespan,
55
+ docs_url=None,
56
+ redoc_url=None,
57
+ )
58
+
59
+ # Middlewares
60
+ app.add_middleware(
61
+ CORSMiddleware,
62
+ allow_origins=[config.origenes_permitidos],
63
+ allow_credentials=True,
64
+ allow_methods=["*"],
65
+ allow_headers=["*"],
66
+ )
67
+ app.add_middleware(GZipMiddleware, minimum_size=1000)
68
+ app.state.limiter = limiter
69
+ app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
70
+ app.add_exception_handler(Exception, exception_handler)
71
+ app.add_exception_handler(HTTPException, http_exception_handler)
72
+
73
+ # Static files
74
+ app.mount("/static", StaticFiles(directory="static"), name="static")
75
+
76
+ @app.get("/favicon.ico", include_in_schema=False)
77
+ async def favicon():
78
+ return FileResponse("static/img/favicon.ico")
79
+
80
+ @app.get("/", include_in_schema=False)
81
+ async def root():
82
+ return {"mensaje": f"Bienvenido a {config.PROJECT_NAME}. Para más información, visita /docs o /redoc."}
83
+
84
+ @app.get("/docs", include_in_schema=False)
85
+ async def custom_swagger_ui_html():
86
+ return get_swagger_ui_html(
87
+ openapi_url=app.openapi_url,
88
+ title=app.title + " - Swagger UI",
89
+ swagger_favicon_url="/static/img/favicon.ico"
90
+ )
91
+
92
+ @app.get("/redoc", include_in_schema=False)
93
+ async def custom_redoc_html():
94
+ return get_redoc_html(
95
+ openapi_url=app.openapi_url,
96
+ title=app.title + " - ReDoc",
97
+ redoc_favicon_url="/static/img/favicon.ico"
98
+ )
99
+
100
+ # Include Routers
101
+ app.include_router(security_router)
102
+ app.include_router(example_router)
@@ -0,0 +1,42 @@
1
+ [project]
2
+ name = "calypso-api"
3
+ version = "0.1.0"
4
+ description = "Calypso API Library and CLI for scaffolding FastAPI projects"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ authors = [
8
+ {name = "Juan Maniglia", email = "juan.maniglia@example.com"}
9
+ ]
10
+ license = {text = "MIT"}
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Operating System :: OS Independent",
15
+ "Framework :: FastAPI",
16
+ ]
17
+ dependencies = [
18
+ "aiosqlite>=0.22.1",
19
+ "asyncpg>=0.31.0",
20
+ "bcrypt>=5.0.0",
21
+ "fastapi>=0.128.0",
22
+ "python-dotenv>=1.2.1",
23
+ "python-jose[cryptography]>=3.5.0",
24
+ "python-multipart>=0.0.22",
25
+ "slowapi>=0.1.9",
26
+ "sqlalchemy>=2.0.46",
27
+ "sqlmodel>=0.0.32",
28
+ "typer>=0.21.1",
29
+ "uvicorn>=0.40.0",
30
+ ]
31
+
32
+ [project.scripts]
33
+ calypso = "calypso_api.cli:app"
34
+
35
+ [build-system]
36
+ requires = ["hatchling"]
37
+ build-backend = "hatchling.build"
38
+
39
+ [dependency-groups]
40
+ dev = [
41
+ "ipython>=9.10.0",
42
+ ]
@@ -0,0 +1,12 @@
1
+
2
+ fastapi
3
+ uvicorn
4
+ sqlalchemy
5
+ asyncpg
6
+ python-jose[cryptography]
7
+ passlib[bcrypt]
8
+ slowapi
9
+ pandas
10
+ pyarrow
11
+ pydantic
12
+ python-multipart
File without changes
@@ -0,0 +1,4 @@
1
+ from calypso_api.cli import app
2
+
3
+ if __name__ == "__main__":
4
+ app()
File without changes
@@ -0,0 +1,44 @@
1
+
2
+ import typer
3
+ import uvicorn
4
+ from calypso_api.core import config
5
+ from pathlib import Path
6
+ from calypso_api.scaffold import generate
7
+
8
+ app = typer.Typer()
9
+
10
+ @app.command()
11
+ def run(
12
+ host: str = "127.0.0.1",
13
+ port: int = 8000,
14
+ reload: bool = True
15
+ ):
16
+ uvicorn.run(
17
+ "calypso_api.main:app",
18
+ host=host,
19
+ port=port,
20
+ reload=reload,
21
+ log_level="info" if config.DEBUG else "warning"
22
+ )
23
+
24
+ @app.command()
25
+ def shell():
26
+ import IPython
27
+ from calypso_api.database.db import engine
28
+
29
+ typer.echo("Opening shell...")
30
+ IPython.embed(header="API Template Shell", colors="neutral")
31
+
32
+ @app.command()
33
+ def init(
34
+ destino: Path = typer.Argument(..., file_okay=False, dir_okay=True, readable=True, writable=True, help="Directorio destino"),
35
+ nombre: str = typer.Argument(..., help="Nombre del proyecto"),
36
+ host: str = typer.Option("127.0.0.1", help="Host para la aplicación"),
37
+ port: int = typer.Option(8000, help="Puerto para la aplicación"),
38
+ docker: bool = typer.Option(True, help="Incluir configuración de Docker")
39
+ ):
40
+ generate(destino, nombre, host, port, docker)
41
+ typer.echo(f"Estructura creada en {destino}")
42
+
43
+ if __name__ == "__main__":
44
+ app()
File without changes
@@ -0,0 +1,23 @@
1
+
2
+ import os
3
+ from typing import List
4
+ from dotenv import load_dotenv
5
+
6
+ load_dotenv()
7
+
8
+ # Configuración de la API
9
+ API_KEY = os.environ.get('API_KEY', 'default_api_key')
10
+ SECRET_KEY = os.environ.get('SECRET_KEY', 'default_secret_key')
11
+ ALGORITHM = os.environ.get('ALGORITHM', 'HS256')
12
+ ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 4
13
+ PROJECT_NAME: str = "API Template"
14
+ PROJECT_DESCRIPTION: str = "Template para nuevas APIs con FastAPI y Typer"
15
+ VERSION: str = "0.1.0"
16
+ API_PREFIX: str = "/api"
17
+ DEBUG: bool = os.environ.get('DEBUG', 'False').lower() == 'true'
18
+
19
+ # Base de datos
20
+ DATABASE_URL = os.environ.get('DATABASE_URL', "sqlite+aiosqlite:///./test.db")
21
+
22
+ # CORS
23
+ ORIGINS: List[str] = ["*"]
File without changes
@@ -0,0 +1,24 @@
1
+
2
+ from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
3
+ from sqlmodel import SQLModel
4
+ from calypso_api.core import config
5
+ from typing import AsyncGenerator
6
+
7
+ engine = create_async_engine(config.DATABASE_URL, echo=config.DEBUG, future=True)
8
+
9
+ async_session_factory = async_sessionmaker(
10
+ bind=engine,
11
+ class_=AsyncSession,
12
+ expire_on_commit=False,
13
+ autocommit=False,
14
+ autoflush=False,
15
+ )
16
+
17
+ async def get_db() -> AsyncGenerator[AsyncSession, None]:
18
+ async with async_session_factory() as session:
19
+ yield session
20
+
21
+ async def init_db():
22
+ async with engine.begin() as conn:
23
+ # await conn.run_sync(SQLModel.metadata.drop_all)
24
+ await conn.run_sync(SQLModel.metadata.create_all)
File without changes
@@ -0,0 +1,38 @@
1
+
2
+ from fastapi import FastAPI
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from contextlib import asynccontextmanager
5
+ from calypso_api.core import config
6
+ from calypso_api.database.db import init_db
7
+ from calypso_api.routes import health
8
+
9
+ @asynccontextmanager
10
+ async def lifespan(app: FastAPI):
11
+ # Startup
12
+ await init_db()
13
+ yield
14
+ # Shutdown
15
+
16
+ app = FastAPI(
17
+ title=config.PROJECT_NAME,
18
+ description=config.PROJECT_DESCRIPTION,
19
+ version=config.VERSION,
20
+ lifespan=lifespan,
21
+ docs_url=f"{config.API_PREFIX}/docs",
22
+ redoc_url=f"{config.API_PREFIX}/redoc",
23
+ openapi_url=f"{config.API_PREFIX}/openapi.json",
24
+ )
25
+
26
+ app.add_middleware(
27
+ CORSMiddleware,
28
+ allow_origins=config.ORIGINS,
29
+ allow_credentials=True,
30
+ allow_methods=["*"],
31
+ allow_headers=["*"],
32
+ )
33
+
34
+ app.include_router(health.router, prefix=config.API_PREFIX)
35
+
36
+ @app.get("/")
37
+ async def root():
38
+ return {"message": f"Welcome to {config.PROJECT_NAME}"}
File without changes
File without changes
@@ -0,0 +1,8 @@
1
+
2
+ from fastapi import APIRouter
3
+
4
+ router = APIRouter(tags=["Health"])
5
+
6
+ @router.get("/health")
7
+ async def health_check():
8
+ return {"status": "ok", "message": "Service is healthy"}