spakky-fastapi 0.17.0__tar.gz → 1.1.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spakky-fastapi
3
- Version: 0.17.0
3
+ Version: 1.1.2
4
4
  Summary: Highly abstracted Framework core to use DDD & DI/IoC & AOP & Etc...
5
5
  Author: Spakky
6
6
  Author-email: sejong418@icloud.com
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: Programming Language :: Python :: 3.12
12
12
  Requires-Dist: fastapi (>=0.109.2,<0.110.0)
13
13
  Requires-Dist: orjson (>=3.9.15,<4.0.0)
14
- Requires-Dist: spakky-core (>=0.15,<0.16)
14
+ Requires-Dist: spakky-core (>=1.1.2,<2.0.0)
15
15
  Requires-Dist: websockets (>=12.0,<13.0)
16
16
  Description-Content-Type: text/markdown
17
17
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "spakky-fastapi"
3
- version = "0.17.0"
3
+ version = "1.1.2"
4
4
  description = "Highly abstracted Framework core to use DDD & DI/IoC & AOP & Etc..."
5
5
  authors = ["Spakky <sejong418@icloud.com>"]
6
6
  readme = "README.md"
@@ -12,7 +12,7 @@ build-backend = "poetry.core.masonry.api"
12
12
  [tool.poetry.dependencies]
13
13
  python = ">=3.10"
14
14
  fastapi = "^0.109.2"
15
- spakky-core = "^0.15"
15
+ spakky-core = "^1.1.2"
16
16
  websockets = "^12.0"
17
17
  orjson = "^3.9.15"
18
18
 
@@ -6,15 +6,14 @@ from dataclasses import InitVar, field, dataclass
6
6
  from fastapi import Depends
7
7
  from fastapi.security import OAuth2PasswordBearer
8
8
  from spakky.aop.advice import Around
9
- from spakky.aop.advisor import IAdvisor, IAsyncAdvisor
10
- from spakky.aop.aspect import Aspect, AsyncAspect
9
+ from spakky.aop.aspect import Aspect, AsyncAspect, IAspect, IAsyncAspect
11
10
  from spakky.aop.error import SpakkyAOPError
12
- from spakky.aop.order import Order
13
11
  from spakky.core.annotation import FunctionAnnotation
14
12
  from spakky.core.types import AsyncFunc, Func, P
15
- from spakky.cryptography.error import InvalidJWTFormatError, JWTDecodingError
16
- from spakky.cryptography.jwt import JWT
17
- from spakky.cryptography.key import Key
13
+ from spakky.pod.order import Order
14
+ from spakky.security.error import InvalidJWTFormatError, JWTDecodingError
15
+ from spakky.security.jwt import JWT
16
+ from spakky.security.key import Key
18
17
 
19
18
  from spakky_fastapi.error import Unauthorized
20
19
 
@@ -52,7 +51,7 @@ class Authenticate(FunctionAnnotation):
52
51
 
53
52
  @Order(1)
54
53
  @Aspect()
55
- class AuthenticationAdvisor(IAdvisor):
54
+ class AuthenticationAspect(IAspect):
56
55
  __logger: Logger
57
56
  __key: Key
58
57
 
@@ -61,9 +60,9 @@ class AuthenticationAdvisor(IAdvisor):
61
60
  self.__logger = logger
62
61
  self.__key = key
63
62
 
64
- @Around(lambda x: Authenticate.contains(x) and not iscoroutinefunction(x))
63
+ @Around(lambda x: Authenticate.exists(x) and not iscoroutinefunction(x))
65
64
  def around(self, joinpoint: Func, *args: Any, **kwargs: Any) -> Any:
66
- annotation: Authenticate = Authenticate.single(joinpoint)
65
+ annotation: Authenticate = Authenticate.get(joinpoint)
67
66
  for keyword in annotation.token_keywords:
68
67
  token: str = kwargs[keyword]
69
68
  try:
@@ -81,7 +80,7 @@ class AuthenticationAdvisor(IAdvisor):
81
80
 
82
81
  @Order(1)
83
82
  @AsyncAspect()
84
- class AsyncAuthenticationAdvisor(IAsyncAdvisor):
83
+ class AsyncAuthenticationAspect(IAsyncAspect):
85
84
  __logger: Logger
86
85
  __key: Key
87
86
 
@@ -90,9 +89,9 @@ class AsyncAuthenticationAdvisor(IAsyncAdvisor):
90
89
  self.__logger = logger
91
90
  self.__key = key
92
91
 
93
- @Around(lambda x: Authenticate.contains(x) and iscoroutinefunction(x))
92
+ @Around(lambda x: Authenticate.exists(x) and iscoroutinefunction(x))
94
93
  async def around_async(self, joinpoint: AsyncFunc, *args: Any, **kwargs: Any) -> Any:
95
- annotation: Authenticate = Authenticate.single(joinpoint)
94
+ annotation: Authenticate = Authenticate.get(joinpoint)
96
95
  for keyword in annotation.token_keywords:
97
96
  token: str = kwargs[keyword]
98
97
  try:
@@ -1,3 +1,4 @@
1
+ import traceback
1
2
  from typing import Callable, Awaitable, TypeAlias
2
3
 
3
4
  from fastapi import Request
@@ -43,6 +44,8 @@ class ErrorHandlingMiddleware(BaseHTTPMiddleware):
43
44
  )
44
45
  # pylint: disable=broad-exception-caught
45
46
  except Exception as e:
47
+ if self.__debug:
48
+ traceback.print_exc() # pragma: no cover
46
49
  error = InternalServerError(e)
47
50
  return ORJSONResponse(
48
51
  content=ErrorResponse(
@@ -0,0 +1,13 @@
1
+ from spakky.application.interfaces.pluggable import IPluggable
2
+ from spakky.application.interfaces.registry import IPodRegistry
3
+
4
+ from spakky_fastapi.aspects.authenticate import (
5
+ AsyncAuthenticationAspect,
6
+ AuthenticationAspect,
7
+ )
8
+
9
+
10
+ class AuthenticatePlugin(IPluggable):
11
+ def register(self, registry: IPodRegistry) -> None:
12
+ registry.register(AuthenticationAspect)
13
+ registry.register(AsyncAuthenticationAspect)
@@ -2,7 +2,7 @@ from logging import Logger
2
2
 
3
3
  from fastapi import FastAPI
4
4
  from spakky.application.interfaces.pluggable import IPluggable
5
- from spakky.application.interfaces.registry import IRegistry
5
+ from spakky.application.interfaces.registry import IPodRegistry
6
6
 
7
7
  from spakky_fastapi.post_processor import FastAPIBeanPostProcessor
8
8
 
@@ -15,8 +15,8 @@ class FastAPIPlugin(IPluggable):
15
15
  self.app = app
16
16
  self.logger = logger
17
17
 
18
- def register(self, registry: IRegistry) -> None:
19
- registry.register_bean_post_processor(
18
+ def register(self, registry: IPodRegistry) -> None:
19
+ registry.register_post_processor(
20
20
  FastAPIBeanPostProcessor(
21
21
  self.app,
22
22
  self.logger,
@@ -1,4 +1,3 @@
1
- from typing import Any
2
1
  from inspect import signature, getmembers
3
2
  from logging import Logger
4
3
  from dataclasses import asdict
@@ -6,8 +5,9 @@ from dataclasses import asdict
6
5
  from fastapi import APIRouter, FastAPI
7
6
  from fastapi.exceptions import FastAPIError
8
7
  from fastapi.utils import create_response_field # type: ignore
9
- from spakky.application.interfaces.bean_container import IBeanContainer
10
- from spakky.application.interfaces.bean_processor import IBeanPostProcessor
8
+ from spakky.application.interfaces.container import IPodContainer
9
+ from spakky.application.interfaces.post_processor import IPodPostProcessor
10
+ from spakky.pod.order import Order
11
11
 
12
12
  from spakky_fastapi.stereotypes.api_controller import (
13
13
  ApiController,
@@ -16,7 +16,8 @@ from spakky_fastapi.stereotypes.api_controller import (
16
16
  )
17
17
 
18
18
 
19
- class FastAPIBeanPostProcessor(IBeanPostProcessor):
19
+ @Order(1)
20
+ class FastAPIBeanPostProcessor(IPodPostProcessor):
20
21
  __app: FastAPI
21
22
  __logger: Logger
22
23
 
@@ -25,14 +26,15 @@ class FastAPIBeanPostProcessor(IBeanPostProcessor):
25
26
  self.__app = app
26
27
  self.__logger = logger
27
28
 
28
- def post_process_bean(self, container: IBeanContainer, bean: Any) -> Any:
29
- if not ApiController.contains(bean):
30
- return bean
31
- controller = ApiController.single(bean)
29
+ def post_process(self, container: IPodContainer, pod: object) -> object:
30
+ if not ApiController.exists(pod):
31
+ return pod
32
+ controller = ApiController.get(pod)
32
33
  router: APIRouter = APIRouter(prefix=controller.prefix, tags=controller.tags)
33
- for name, method in getmembers(bean, callable):
34
- route: Route | None = Route.single_or_none(method)
35
- websocket_route: WebSocketRoute | None = WebSocketRoute.single_or_none(method)
34
+ print(f"CONTROLLER {type(pod).__name__}")
35
+ for name, method in getmembers(pod, callable):
36
+ route: Route | None = Route.get_or_none(method)
37
+ websocket_route: WebSocketRoute | None = WebSocketRoute.get_or_none(method)
36
38
  if route is None and websocket_route is None:
37
39
  continue
38
40
  if route is not None:
@@ -56,13 +58,13 @@ class FastAPIBeanPostProcessor(IBeanPostProcessor):
56
58
  router.add_api_route(endpoint=method, **asdict(route))
57
59
  if websocket_route is not None:
58
60
  # pylint: disable=line-too-long
59
- self.__logger.info(
60
- f"[{type(self).__name__}] [WebSocket] {controller.prefix}{websocket_route.path} -> {method.__qualname__}"
61
- )
61
+ # self.__logger.info(
62
+ # f"[{type(self).__name__}] [WebSocket] {controller.prefix}{websocket_route.path} -> {method.__qualname__}"
63
+ # )
62
64
  if websocket_route.name is None:
63
65
  websocket_route.name = " ".join(
64
66
  [x.capitalize() for x in name.split("_")]
65
67
  )
66
68
  router.add_api_websocket_route(endpoint=method, **asdict(websocket_route))
67
69
  self.__app.include_router(router)
68
- return bean
70
+ return pod
@@ -1,13 +0,0 @@
1
- from spakky.application.interfaces.pluggable import IPluggable
2
- from spakky.application.interfaces.registry import IRegistry
3
-
4
- from spakky_fastapi.extensions.authenticate import (
5
- AsyncAuthenticationAdvisor,
6
- AuthenticationAdvisor,
7
- )
8
-
9
-
10
- class AuthenticatePlugin(IPluggable):
11
- def register(self, registry: IRegistry) -> None:
12
- registry.register_bean(AuthenticationAdvisor)
13
- registry.register_bean(AsyncAuthenticationAdvisor)