Skip to content

Commit

Permalink
Add role
Browse files Browse the repository at this point in the history
  • Loading branch information
goFrendiAsgard committed Dec 31, 2024
1 parent ea001eb commit 9376dce
Show file tree
Hide file tree
Showing 35 changed files with 470 additions and 187 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ async def validate_create_my_app_name_entity(ctx: AnyContext):
"alembic upgrade head",
Cmd(
'alembic revision --autogenerate -m "create_{to_snake_case(ctx.input.entity)}_table"', # noqa
auto_render=True,
),
],
render_cmd=False,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from logging import Logger

from my_app_name.common.base_service import BaseService
from my_app_name.common.parser import parse_filter_param, parse_sort_param
from my_app_name.common.parser_factory import parse_filter_param, parse_sort_param
from my_app_name.module.my_module.service.my_entity.repository.my_entity_repository import (
MyEntityRepository,
)
Expand All @@ -13,8 +15,8 @@


class MyEntityService(BaseService):
def __init__(self, my_entity_repository: MyEntityRepository):
super().__init__()
def __init__(self, logger: Logger, my_entity_repository: MyEntityRepository):
super().__init__(logger)
self.my_entity_repository = my_entity_repository

@BaseService.route(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from my_app_name.common.logger_factory import logger
from my_app_name.module.my_module.service.my_entity.my_entity_service import (
MyEntityService,
)
from my_app_name.module.my_module.service.my_entity.repository.my_entity_repository_factory import (
my_entity_repository,
)

my_entity_service = MyEntityService(my_entity_repository=my_entity_repository)
my_entity_service = MyEntityService(logger, my_entity_repository=my_entity_repository)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from my_app_name.common.db_engine import engine
from my_app_name.common.db_engine_factory import db_engine
from my_app_name.config import APP_REPOSITORY_TYPE
from my_app_name.module.my_module.service.my_entity.repository.my_entity_db_repository import (
MyEntityDBRepository,
Expand All @@ -8,6 +8,6 @@
)

if APP_REPOSITORY_TYPE == "db":
my_entity_repository: MyEntityRepository = MyEntityDBRepository(engine)
my_entity_repository: MyEntityRepository = MyEntityDBRepository(db_engine)
else:
my_entity_repository: MyEntityRepository = None
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from fastapi import FastAPI
from my_app_name.common.app import app
from my_app_name.common.app_factory import app
from my_app_name.common.schema import BasicResponse
from my_app_name.config import APP_MAIN_MODULE, APP_MODE, APP_MODULES

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import os

from fastapi import FastAPI
from my_app_name.common.db_engine_factory import db_engine
from my_app_name.common.util.app import (
create_default_app_lifespan,
get_default_app_title,
serve_docs,
serve_static_dir,
)
from my_app_name.config import (
APP_GATEWAY_FAVICON_PATH,
APP_GATEWAY_TITLE,
APP_GATEWAY_VIEW_PATH,
APP_MODE,
APP_MODULES,
APP_VERSION,
)

app_title = get_default_app_title(APP_GATEWAY_TITLE, mode=APP_MODE, modules=APP_MODULES)
app = FastAPI(
title=app_title,
version=APP_VERSION,
lifespan=create_default_app_lifespan(db_engine),
docs_url=None,
)

serve_static_dir(app, os.path.join(APP_GATEWAY_VIEW_PATH, "static"))
serve_docs(app, app_title=app_title, favicon_url=APP_GATEWAY_FAVICON_PATH)
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import inspect
from enum import Enum
from functools import partial
from logging import Logger
from typing import Any, Callable, Sequence

import httpx
from fastapi import APIRouter, Depends, params
from my_app_name.common.error import ClientAPIError
from my_app_name.common.log import logger
from pydantic import BaseModel


Expand Down Expand Up @@ -37,12 +37,17 @@ def __init__(
class BaseService:
_route_params: dict[str, RouteParam] = {}

def __init__(self):
def __init__(self, logger: Logger):
self._logger = logger
self._route_params: dict[str, RouteParam] = {}
for name, method in self.__class__.__dict__.items():
if hasattr(method, "__route_param__"):
self._route_params[name] = getattr(method, "__route_param__")

@property
def logger(self) -> Logger:
return self._logger

@classmethod
def route(
cls,
Expand Down Expand Up @@ -96,10 +101,10 @@ def as_direct_client(self):
Dynamically create a direct client class.
"""
_methods = self._route_params
DirectClient = create_client_class("DirectClient")
DirectClient = _create_client_class("DirectClient")
for name, details in _methods.items():
func = details.func
client_method = create_direct_client_method(func, self)
client_method = _create_direct_client_method(self._logger, func, self)
# Use __get__ to make a bounded method,
# ensuring that client_method use DirectClient as `self`
setattr(DirectClient, name, client_method.__get__(DirectClient))
Expand All @@ -110,10 +115,10 @@ def as_api_client(self, base_url: str):
Dynamically create an API client class.
"""
_methods = self._route_params
APIClient = create_client_class("APIClient")
APIClient = _create_client_class("APIClient")
# Dynamically generate methods
for name, param in _methods.items():
client_method = create_api_client_method(param, base_url)
client_method = _create_api_client_method(self._logger, param, base_url)
# Use __get__ to make a bounded method,
# ensuring that client_method use APIClient as `self`
setattr(APIClient, name, client_method.__get__(APIClient))
Expand All @@ -140,22 +145,22 @@ def serve_route(self, app: APIRouter):
)


def create_client_class(name):
def _create_client_class(name):
class Client:
pass

Client.__name__ = name
return Client


def create_direct_client_method(func: Callable, service: BaseService):
def _create_direct_client_method(logger: Logger, func: Callable, service: BaseService):
async def client_method(self, *args, **kwargs):
return await func(service, *args, **kwargs)

return client_method


def create_api_client_method(param: RouteParam, base_url: str):
def _create_api_client_method(logger: Logger, param: RouteParam, base_url: str):
async def client_method(*args, **kwargs):
url = base_url + param.path
method = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
from sqlmodel import create_engine

connect_args = {"check_same_thread": False}
engine = create_engine(APP_DB_URL, connect_args=connect_args, echo=True)
db_engine = create_engine(APP_DB_URL, connect_args=connect_args, echo=True)
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
)

# Create a logger for your application
logger = logging.getLogger("fastapp")
logger: logging.Logger = logging.getLogger("fastapp")

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from my_app_name.common.util.parser import (
create_default_filter_param_parser,
create_default_sort_param_parser,
)

parse_filter_param = create_default_filter_param_parser()
parse_sort_param = create_default_sort_param_parser()
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import os
from contextlib import asynccontextmanager

from fastapi import FastAPI, HTTPException
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from sqlalchemy.engine import Engine
from sqlmodel import SQLModel
from starlette.types import Lifespan


def get_default_app_title(app_title: str, mode: str, modules: list[str] = []) -> str:
if mode == "monolith":
return app_title
return f"{app_title} - {', '.join(modules)}"


def create_default_app_lifespan(db_engine: Engine) -> Lifespan:
@asynccontextmanager
async def default_app_lifespan(app: FastAPI):
SQLModel.metadata.create_all(db_engine)
yield

return default_app_lifespan


def serve_static_dir(app: FastAPI, static_dir: str):
app.mount("/static", StaticFiles(directory=static_dir), name="static")

# Serve static files
@app.get("/static/{file_path:path}", include_in_schema=False)
async def static_files(file_path: str):
full_path = os.path.join(static_dir, file_path)
if os.path.isfile(full_path):
return FileResponse(full_path)
raise HTTPException(status_code=404, detail="File not found")


def serve_docs(app: FastAPI, app_title: str, favicon_url: str):
@app.get("/docs", include_in_schema=False)
async def swagger_ui_html():
return get_swagger_ui_html(
openapi_url="/openapi.json",
title=app_title,
swagger_favicon_url=favicon_url,
)
Loading

0 comments on commit 9376dce

Please sign in to comment.