Skip to content

Commit

Permalink
refactor: use singleton decorator to extract Litestar
Browse files Browse the repository at this point in the history
  • Loading branch information
winstxnhdw committed Aug 31, 2024
1 parent a923953 commit a9a8007
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 44 deletions.
3 changes: 1 addition & 2 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from granian import Granian
from granian.constants import Interfaces

from server import App
from server.config import Config


Expand All @@ -12,7 +11,7 @@ def main():
programmatically run the server with Granian
"""
granian = Granian(
f'{App.__module__}:{App.__name__}',
'server:app',
'0.0.0.0',
Config.server_port,
Interfaces.ASGI,
Expand Down
27 changes: 4 additions & 23 deletions server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from litestar.openapi import OpenAPIConfig
from litestar.openapi.spec import Server
from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR
from litestar.types import LifeSpanReceive, LifeSpanScope, LifeSpanSend, Receive, Scope, Send
from picologging import getLogger

from server.api import v1
from server.config import Config
from server.lifespans import load_model
from server.singleton import singleton


def exception_handler(_, exception: Exception) -> Response[dict[str, str]]:
Expand All @@ -29,30 +29,11 @@ def exception_handler(_, exception: Exception) -> Response[dict[str, str]]:
)


class App:
"""
Summary
-------
the ASGI application wrapper
Parameters
----------
scope (Scope) : the ASGI scope
receive (Receive) : the ASGI receive channel
send (Send) : the ASGI send channel
"""

asgi = Litestar(
@singleton
def app() -> Litestar:
return Litestar(
openapi_config=OpenAPIConfig(title='CapGen', version='1.0.0', servers=[Server(url=Config.server_root_path)]),
exception_handlers={HTTP_500_INTERNAL_SERVER_ERROR: exception_handler},
route_handlers=[v1],
lifespan=[load_model],
)

async def __new__( # pylint: disable=invalid-overridden-method
cls,
scope: Scope | LifeSpanScope,
receive: Receive | LifeSpanReceive,
send: Send | LifeSpanSend,
):
await cls.asgi(scope, receive, send)
19 changes: 2 additions & 17 deletions server/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,9 @@

from pydantic_settings import BaseSettings

T = TypeVar('T')


def singleton(cls: type[T]) -> T:
"""
Summary
-------
a decorator to make a class a singleton
from server.singleton import singleton

Parameters
----------
cls (type[T]) : the class to make a singleton
Returns
-------
instance (T) : the singleton instance
"""
return cls()
T = TypeVar('T')


@singleton
Expand Down
18 changes: 18 additions & 0 deletions server/singleton.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from typing import Callable


def singleton[T](callable_object: Callable[[], T]) -> T:
"""
Summary
-------
a decorator to transform a callable/class to a singleton
Parameters
----------
callable_object (Callable[[], T]) : the callable to transform
Returns
-------
instance (T) : the singleton
"""
return callable_object()
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
from litestar.testing import AsyncTestClient
from pytest import fixture

from server import App
from server import app


@fixture(scope='function')
async def client() -> AsyncIterator[AsyncTestClient[Litestar]]:
async with AsyncTestClient(app=App.asgi) as client:
async with AsyncTestClient(app=app) as client:
yield client

0 comments on commit a9a8007

Please sign in to comment.