project: ruff check and format
This commit is contained in:
parent
0a9d941eea
commit
1e906fc3f0
27 changed files with 93 additions and 63 deletions
|
|
@ -17,6 +17,7 @@ Exports:
|
|||
- Dependencies should be used for db model get and validation where possible
|
||||
- Verify module level docstring is still accurate after updates
|
||||
"""
|
||||
|
||||
import threading
|
||||
from typing import Annotated, Optional
|
||||
|
||||
|
|
@ -38,14 +39,16 @@ async def start_timer(request: Request, interval: int):
|
|||
print("ping")
|
||||
|
||||
stop_event = threading.Event()
|
||||
timer = create_timer(func=example_timer_target, interval=interval, stop_event=stop_event)
|
||||
timer = create_timer(
|
||||
func=example_timer_target, interval=interval, stop_event=stop_event
|
||||
)
|
||||
timer_ident = "example_timer"
|
||||
|
||||
timer_tracker = {
|
||||
"ident": timer_ident,
|
||||
"interval": interval,
|
||||
"stop_event": stop_event,
|
||||
"timer": timer
|
||||
"timer": timer,
|
||||
}
|
||||
timer.start()
|
||||
|
||||
|
|
@ -58,7 +61,10 @@ async def start_timer(request: Request, interval: int):
|
|||
async def stop_timer(request: Request, ident: str):
|
||||
timers = request.app.state.timers
|
||||
|
||||
idx, timer_tracker = next(((i, timer) for i, timer in enumerate(timers) if timer["ident"] == ident), (None, None))
|
||||
idx, timer_tracker = next(
|
||||
((i, timer) for i, timer in enumerate(timers) if timer["ident"] == ident),
|
||||
(None, None),
|
||||
)
|
||||
|
||||
if not timer_tracker:
|
||||
raise HTTPException(status_code=404, detail="Timer not found")
|
||||
|
|
@ -72,9 +78,14 @@ async def stop_timer(request: Request, ident: str):
|
|||
|
||||
|
||||
@router.get("/hub/access")
|
||||
async def test_hub_access(headers: header_dependency, client: http_client_dependency, org_name: Annotated[str, Query()],
|
||||
resource_name: Annotated[str, Query()] = "example_resource",
|
||||
action: Annotated[str, Query()] = "read", instance: Optional[Annotated[str, Query()]] = None):
|
||||
async def test_hub_access(
|
||||
headers: header_dependency,
|
||||
client: http_client_dependency,
|
||||
org_name: Annotated[str, Query()],
|
||||
resource_name: Annotated[str, Query()] = "example_resource",
|
||||
action: Annotated[str, Query()] = "read",
|
||||
instance: Optional[Annotated[str, Query()]] = None,
|
||||
):
|
||||
rn = generate_resource_name(resource=resource_name, org=org_name, instance=instance)
|
||||
|
||||
request_body = {
|
||||
|
|
@ -83,33 +94,28 @@ async def test_hub_access(headers: header_dependency, client: http_client_depend
|
|||
}
|
||||
|
||||
hub_response = await client.post(
|
||||
f"http://localhost:8001/api/v1/iam/can_act_on_resource",
|
||||
"http://localhost:8001/api/v1/iam/can_act_on_resource",
|
||||
headers=headers,
|
||||
json=request_body
|
||||
json=request_body,
|
||||
)
|
||||
|
||||
response = {
|
||||
"response": {
|
||||
"status": hub_response.status_code,
|
||||
"json": hub_response.json()
|
||||
}
|
||||
"response": {"status": hub_response.status_code, "json": hub_response.json()}
|
||||
}
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@router.get("/hub/user")
|
||||
async def test_hub_user_details(headers: header_dependency, client: http_client_dependency):
|
||||
async def test_hub_user_details(
|
||||
headers: header_dependency, client: http_client_dependency
|
||||
):
|
||||
hub_response = await client.get(
|
||||
f"http://localhost:8001/api/v1/user/self/db",
|
||||
headers=headers
|
||||
"http://localhost:8001/api/v1/user/self/db", headers=headers
|
||||
)
|
||||
|
||||
response = {
|
||||
"response": {
|
||||
"status": hub_response.status_code,
|
||||
"json": hub_response.json()
|
||||
}
|
||||
"response": {"status": hub_response.status_code, "json": hub_response.json()}
|
||||
}
|
||||
|
||||
return response
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
"""
|
||||
This module hooks the routers for the main endpoints into a single router for importing to the app.
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from src.auth.router import router as auth_router
|
||||
from src._module_template.router import router as template_router
|
||||
|
||||
|
||||
api_router = APIRouter(
|
||||
prefix="/api/v1"
|
||||
)
|
||||
api_router = APIRouter(prefix="/api/v1")
|
||||
|
||||
api_router.include_router(auth_router)
|
||||
api_router.include_router(template_router)
|
||||
|
|
|
|||
|
|
@ -4,14 +4,15 @@ Configurations for the auth module
|
|||
Exports:
|
||||
- auth_settings: Contains OIDC & hub access information
|
||||
"""
|
||||
|
||||
from src.config import CustomBaseSettings
|
||||
|
||||
|
||||
class AuthConfig(CustomBaseSettings):
|
||||
OIDC_CONFIG: str = ""
|
||||
CLIENT_ID: str = ""
|
||||
OIDC_CONFIG: str = ""
|
||||
CLIENT_ID: str = ""
|
||||
|
||||
HUB_ACCESS_KEY: str = ""
|
||||
HUB_ACCESS_KEY: str = ""
|
||||
|
||||
|
||||
auth_settings = AuthConfig()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ Auth dependencies
|
|||
|
||||
Exports:
|
||||
"""
|
||||
|
||||
from typing import Annotated, Any
|
||||
|
||||
from fastapi import Depends
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Module specific exceptions for the auth module
|
|||
Exceptions:
|
||||
- UnauthorizedException: Takes an optional message string
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Router endpoints for the auth module
|
|||
Exports:
|
||||
- router: fastapi.APIRouter
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(
|
||||
|
|
|
|||
|
|
@ -16,27 +16,28 @@ from src.constants import Environment
|
|||
|
||||
|
||||
class CustomBaseSettings(BaseSettings):
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env", env_file_encoding="utf-8", extra="ignore"
|
||||
)
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env", env_file_encoding="utf-8", extra="ignore"
|
||||
)
|
||||
|
||||
|
||||
class Config(CustomBaseSettings):
|
||||
APP_VERSION: str = "0.1"
|
||||
ENVIRONMENT: Environment = Environment.PRODUCTION
|
||||
SECRET_KEY: SecretStr = ""
|
||||
DISABLE_AUTH: bool = False
|
||||
SERVICE_NAME: str = "template_app"
|
||||
HUB_ADDRESS: str = "http://localhost:8000"
|
||||
APP_VERSION: str = "0.1"
|
||||
ENVIRONMENT: Environment = Environment.PRODUCTION
|
||||
SECRET_KEY: SecretStr = ""
|
||||
DISABLE_AUTH: bool = False
|
||||
SERVICE_NAME: str = "template_app"
|
||||
HUB_ADDRESS: str = "http://localhost:8000"
|
||||
|
||||
CORS_ORIGINS: list[str] = ["*"]
|
||||
CORS_ORIGINS_REGEX: str | None = None
|
||||
CORS_HEADERS: list[str] = ["*"]
|
||||
CORS_ORIGINS: list[str] = ["*"]
|
||||
CORS_ORIGINS_REGEX: str | None = None
|
||||
CORS_HEADERS: list[str] = ["*"]
|
||||
|
||||
DATABASE_NAME: str = "fastapi-exp"
|
||||
DATABASE_PORT: str = "5432"
|
||||
DATABASE_HOSTNAME: str = "localhost"
|
||||
DATABASE_CREDENTIALS: SecretStr = ""
|
||||
|
||||
DATABASE_NAME: str = "fastapi-exp"
|
||||
DATABASE_PORT: str = "5432"
|
||||
DATABASE_HOSTNAME: str = "localhost"
|
||||
DATABASE_CREDENTIALS: SecretStr = ""
|
||||
|
||||
settings = Config()
|
||||
|
||||
|
|
@ -45,17 +46,21 @@ DATABASE_PORT = settings.DATABASE_PORT
|
|||
DATABASE_HOSTNAME = settings.DATABASE_HOSTNAME
|
||||
DATABASE_CREDENTIALS = settings.DATABASE_CREDENTIALS.get_secret_value()
|
||||
# this will support special chars for credentials
|
||||
_DATABASE_CREDENTIAL_USER, _DATABASE_CREDENTIAL_PASSWORD = str(DATABASE_CREDENTIALS).split(":")
|
||||
_DATABASE_CREDENTIAL_USER, _DATABASE_CREDENTIAL_PASSWORD = str(
|
||||
DATABASE_CREDENTIALS
|
||||
).split(":")
|
||||
_QUOTED_DATABASE_PASSWORD = parse.quote_plus(str(_DATABASE_CREDENTIAL_PASSWORD))
|
||||
|
||||
SQLALCHEMY_DATABASE_URI = SecretStr(f"postgresql+psycopg://{_DATABASE_CREDENTIAL_USER}:{_QUOTED_DATABASE_PASSWORD}@{DATABASE_HOSTNAME}:{DATABASE_PORT}/{DATABASE_NAME}")
|
||||
SQLALCHEMY_DATABASE_URI = SecretStr(
|
||||
f"postgresql+psycopg://{_DATABASE_CREDENTIAL_USER}:{_QUOTED_DATABASE_PASSWORD}@{DATABASE_HOSTNAME}:{DATABASE_PORT}/{DATABASE_NAME}"
|
||||
)
|
||||
|
||||
if settings.ENVIRONMENT == Environment.TESTING:
|
||||
SQLALCHEMY_DATABASE_URI = SecretStr("sqlite:///:memory:")
|
||||
SQLALCHEMY_DATABASE_URI = SecretStr("sqlite:///:memory:")
|
||||
|
||||
app_configs: dict[str, Any] = {"title": "App API"}
|
||||
if settings.ENVIRONMENT.is_deployed:
|
||||
app_configs["root_path"] = f"/v{settings.APP_VERSION}"
|
||||
app_configs["root_path"] = f"/v{settings.APP_VERSION}"
|
||||
|
||||
if not settings.ENVIRONMENT.is_debug:
|
||||
app_configs["openapi_url"] = None # hide docs
|
||||
app_configs["openapi_url"] = None # hide docs
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Global constants
|
|||
Exports:
|
||||
- Environment(StrEnum): LOCAL, TESTING, STAGING, PRODUCTION
|
||||
"""
|
||||
|
||||
from enum import StrEnum, auto
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Exports:
|
|||
- db_dependency
|
||||
- Base (sqlalchemy base model)
|
||||
"""
|
||||
|
||||
from typing import Annotated
|
||||
from sqlalchemy import create_engine, StaticPool
|
||||
from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session
|
||||
|
|
@ -16,7 +17,11 @@ from src.config import SQLALCHEMY_DATABASE_URI, settings as global_settings
|
|||
|
||||
if global_settings.ENVIRONMENT == Environment.TESTING:
|
||||
connect_args = {"check_same_thread": False}
|
||||
engine = create_engine(SQLALCHEMY_DATABASE_URI.get_secret_value(), connect_args=connect_args, poolclass=StaticPool)
|
||||
engine = create_engine(
|
||||
SQLALCHEMY_DATABASE_URI.get_secret_value(),
|
||||
connect_args=connect_args,
|
||||
poolclass=StaticPool,
|
||||
)
|
||||
else:
|
||||
engine = create_engine(SQLALCHEMY_DATABASE_URI.get_secret_value())
|
||||
|
||||
|
|
@ -36,5 +41,7 @@ def get_db():
|
|||
|
||||
|
||||
db_dependency = Annotated[Session, Depends(get_db)]
|
||||
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -3,13 +3,16 @@ Global dependencies
|
|||
|
||||
Exports:
|
||||
"""
|
||||
|
||||
import httpx
|
||||
|
||||
from typing import Annotated
|
||||
from fastapi import Depends
|
||||
|
||||
|
||||
async def create_http_client():
|
||||
async with httpx.AsyncClient() as client:
|
||||
yield client
|
||||
|
||||
|
||||
http_client_dependency = Annotated[httpx.AsyncClient, Depends(create_http_client)]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Exports:
|
|||
- UnprocessableContentException
|
||||
- ConflictException
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Application root file: Inits the FastAPI application
|
|||
Prometheus client mounted at /metrics endpoint
|
||||
Middleware: Session, CORS
|
||||
"""
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import AsyncGenerator
|
||||
from prometheus_client import make_asgi_app
|
||||
|
|
@ -44,7 +45,7 @@ app = FastAPI(
|
|||
"scopes": "openid profile email",
|
||||
},
|
||||
openapi_tags=tags_metadata,
|
||||
**app_configs
|
||||
**app_configs,
|
||||
)
|
||||
|
||||
metrics_app = make_asgi_app()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
"""
|
||||
Global database models
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Exports:
|
|||
- CustomBaseModel: Schema used for all other Pydantic models
|
||||
- ResourceName
|
||||
"""
|
||||
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ Global non-business-logic reusable functions and classes
|
|||
|
||||
Exports:
|
||||
"""
|
||||
|
||||
import threading
|
||||
from typing import Callable, Optional
|
||||
|
||||
|
|
@ -18,7 +19,9 @@ def create_timer(func: Callable, interval: int, stop_event: threading.Event):
|
|||
return threading.Thread(target=target, daemon=True)
|
||||
|
||||
|
||||
def generate_resource_name(org: str, resource: str, instance: Optional[str] = None) -> ResourceName:
|
||||
def generate_resource_name(
|
||||
org: str, resource: str, instance: Optional[str] = None
|
||||
) -> ResourceName:
|
||||
rn = ResourceName(
|
||||
service=settings.SERVICE_NAME,
|
||||
organisation=org,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue