fastapi-factory-utilities 0.3.3__py3-none-any.whl → 0.8.2__py3-none-any.whl

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 (75) hide show
  1. fastapi_factory_utilities/core/api/__init__.py +1 -1
  2. fastapi_factory_utilities/core/api/v1/sys/health.py +1 -1
  3. fastapi_factory_utilities/core/app/__init__.py +4 -4
  4. fastapi_factory_utilities/core/app/application.py +22 -26
  5. fastapi_factory_utilities/core/app/builder.py +19 -35
  6. fastapi_factory_utilities/core/app/config.py +2 -0
  7. fastapi_factory_utilities/core/app/fastapi_builder.py +3 -2
  8. fastapi_factory_utilities/core/exceptions.py +64 -28
  9. fastapi_factory_utilities/core/plugins/__init__.py +2 -31
  10. fastapi_factory_utilities/core/plugins/abstracts.py +40 -0
  11. fastapi_factory_utilities/core/plugins/aiopika/__init__.py +25 -0
  12. fastapi_factory_utilities/core/plugins/aiopika/abstract.py +48 -0
  13. fastapi_factory_utilities/core/plugins/aiopika/configs.py +85 -0
  14. fastapi_factory_utilities/core/plugins/aiopika/depends.py +20 -0
  15. fastapi_factory_utilities/core/plugins/aiopika/exceptions.py +29 -0
  16. fastapi_factory_utilities/core/plugins/aiopika/exchange.py +69 -0
  17. fastapi_factory_utilities/core/plugins/aiopika/listener/__init__.py +7 -0
  18. fastapi_factory_utilities/core/plugins/aiopika/listener/abstract.py +72 -0
  19. fastapi_factory_utilities/core/plugins/aiopika/message.py +86 -0
  20. fastapi_factory_utilities/core/plugins/aiopika/plugins.py +84 -0
  21. fastapi_factory_utilities/core/plugins/aiopika/publisher/__init__.py +7 -0
  22. fastapi_factory_utilities/core/plugins/aiopika/publisher/abstract.py +66 -0
  23. fastapi_factory_utilities/core/plugins/aiopika/queue.py +88 -0
  24. fastapi_factory_utilities/core/plugins/odm_plugin/__init__.py +14 -157
  25. fastapi_factory_utilities/core/plugins/odm_plugin/builder.py +4 -3
  26. fastapi_factory_utilities/core/plugins/odm_plugin/configs.py +1 -1
  27. fastapi_factory_utilities/core/plugins/odm_plugin/documents.py +1 -1
  28. fastapi_factory_utilities/core/plugins/odm_plugin/helpers.py +16 -0
  29. fastapi_factory_utilities/core/plugins/odm_plugin/plugins.py +155 -0
  30. fastapi_factory_utilities/core/plugins/odm_plugin/repositories.py +12 -23
  31. fastapi_factory_utilities/core/plugins/opentelemetry_plugin/__init__.py +8 -115
  32. fastapi_factory_utilities/core/plugins/opentelemetry_plugin/instruments/__init__.py +85 -0
  33. fastapi_factory_utilities/core/plugins/opentelemetry_plugin/plugins.py +137 -0
  34. fastapi_factory_utilities/core/plugins/taskiq_plugins/__init__.py +31 -0
  35. fastapi_factory_utilities/core/plugins/taskiq_plugins/configs.py +12 -0
  36. fastapi_factory_utilities/core/plugins/taskiq_plugins/depends.py +51 -0
  37. fastapi_factory_utilities/core/plugins/taskiq_plugins/exceptions.py +13 -0
  38. fastapi_factory_utilities/core/plugins/taskiq_plugins/plugin.py +41 -0
  39. fastapi_factory_utilities/core/plugins/taskiq_plugins/schedulers.py +187 -0
  40. fastapi_factory_utilities/core/protocols.py +1 -54
  41. fastapi_factory_utilities/core/security/__init__.py +5 -0
  42. fastapi_factory_utilities/core/security/abstracts.py +42 -0
  43. fastapi_factory_utilities/core/security/jwt/__init__.py +41 -0
  44. fastapi_factory_utilities/core/security/jwt/configs.py +32 -0
  45. fastapi_factory_utilities/core/security/jwt/decoders.py +130 -0
  46. fastapi_factory_utilities/core/security/jwt/exceptions.py +23 -0
  47. fastapi_factory_utilities/core/security/jwt/objects.py +107 -0
  48. fastapi_factory_utilities/core/security/jwt/services.py +176 -0
  49. fastapi_factory_utilities/core/security/jwt/stores.py +43 -0
  50. fastapi_factory_utilities/core/security/jwt/types.py +9 -0
  51. fastapi_factory_utilities/core/security/jwt/verifiers.py +46 -0
  52. fastapi_factory_utilities/core/security/kratos.py +53 -33
  53. fastapi_factory_utilities/core/services/hydra/__init__.py +20 -0
  54. fastapi_factory_utilities/core/services/hydra/exceptions.py +15 -0
  55. fastapi_factory_utilities/core/services/hydra/objects.py +26 -0
  56. fastapi_factory_utilities/core/services/hydra/services.py +200 -0
  57. fastapi_factory_utilities/core/services/status/__init__.py +2 -2
  58. fastapi_factory_utilities/core/services/status/exceptions.py +1 -1
  59. fastapi_factory_utilities/core/utils/status.py +2 -1
  60. fastapi_factory_utilities/core/utils/yaml_reader.py +1 -1
  61. fastapi_factory_utilities/example/app.py +15 -5
  62. fastapi_factory_utilities/example/entities/books/__init__.py +1 -1
  63. fastapi_factory_utilities/example/models/books/__init__.py +1 -1
  64. {fastapi_factory_utilities-0.3.3.dist-info → fastapi_factory_utilities-0.8.2.dist-info}/METADATA +21 -15
  65. fastapi_factory_utilities-0.8.2.dist-info/RECORD +111 -0
  66. {fastapi_factory_utilities-0.3.3.dist-info → fastapi_factory_utilities-0.8.2.dist-info}/WHEEL +1 -1
  67. fastapi_factory_utilities/core/app/plugin_manager/__init__.py +0 -15
  68. fastapi_factory_utilities/core/app/plugin_manager/exceptions.py +0 -33
  69. fastapi_factory_utilities/core/app/plugin_manager/plugin_manager.py +0 -190
  70. fastapi_factory_utilities/core/plugins/example/__init__.py +0 -31
  71. fastapi_factory_utilities/core/plugins/httpx_plugin/__init__.py +0 -31
  72. fastapi_factory_utilities/core/security/jwt.py +0 -158
  73. fastapi_factory_utilities-0.3.3.dist-info/RECORD +0 -78
  74. {fastapi_factory_utilities-0.3.3.dist-info → fastapi_factory_utilities-0.8.2.dist-info}/entry_points.txt +0 -0
  75. {fastapi_factory_utilities-0.3.3.dist-info → fastapi_factory_utilities-0.8.2.dist-info/licenses}/LICENSE +0 -0
@@ -1,32 +1,39 @@
1
1
  """Provide Kratos Session and Identity classes."""
2
2
 
3
- from typing import Annotated
3
+ from http import HTTPStatus
4
4
 
5
- from fastapi import Depends, HTTPException, Request
5
+ from fastapi import HTTPException, Request
6
6
 
7
+ from fastapi_factory_utilities.core.security.abstracts import AuthenticationAbstract
7
8
  from fastapi_factory_utilities.core.services.kratos import (
8
9
  KratosOperationError,
9
10
  KratosService,
10
11
  KratosSessionInvalidError,
11
12
  KratosSessionObject,
12
- depends_kratos_service,
13
13
  )
14
14
 
15
15
 
16
- class KratosSessionAuthentication:
16
+ class KratosSessionAuthenticationService(AuthenticationAbstract):
17
17
  """Kratos Session class."""
18
18
 
19
19
  DEFAULT_COOKIE_NAME: str = "ory_kratos_session"
20
20
 
21
- def __init__(self, cookie_name: str = DEFAULT_COOKIE_NAME) -> None:
21
+ def __init__(
22
+ self, kratos_service: KratosService, cookie_name: str = DEFAULT_COOKIE_NAME, raise_exception: bool = True
23
+ ) -> None:
22
24
  """Initialize the KratosSessionAuthentication class.
23
25
 
24
26
  Args:
25
- cookie_name (str): Name of the cookie to extract the session
27
+ kratos_service (KratosService): Kratos service object.
28
+ cookie_name (str): Name of the cookie to extract the session.
29
+ raise_exception (bool): Whether to raise an exception or return None.
26
30
  """
31
+ self._kratos_service: KratosService = kratos_service
27
32
  self._cookie_name: str = cookie_name
33
+ self._session: KratosSessionObject
34
+ super().__init__(raise_exception=raise_exception)
28
35
 
29
- def _extract_cookie(self, request: Request) -> str:
36
+ def _extract_cookie(self, request: Request) -> str | None:
30
37
  """Extract the cookie from the request.
31
38
 
32
39
  Args:
@@ -38,17 +45,18 @@ class KratosSessionAuthentication:
38
45
  Raises:
39
46
  HTTPException: If the cookie is missing.
40
47
  """
41
- cookie: str | None = request.cookies.get(self._cookie_name)
42
- if not cookie:
43
- raise HTTPException(
44
- status_code=401,
45
- detail="Missing Credentials",
46
- )
47
- return cookie
48
+ return request.cookies.get(self._cookie_name, None)
49
+
50
+ @property
51
+ def session(self) -> KratosSessionObject:
52
+ """Get the Kratos session.
53
+
54
+ Returns:
55
+ KratosSessionObject: Kratos session object.
56
+ """
57
+ return self._session
48
58
 
49
- async def __call__(
50
- self, request: Request, kratos_service: Annotated[KratosService, Depends(depends_kratos_service)]
51
- ) -> KratosSessionObject:
59
+ async def authenticate(self, request: Request) -> None:
52
60
  """Extract the Kratos session from the request.
53
61
 
54
62
  Args:
@@ -56,23 +64,35 @@ class KratosSessionAuthentication:
56
64
  kratos_service (KratosService): Kratos service object.
57
65
 
58
66
  Returns:
59
- KratosSessionObject: Kratos session object.
67
+ None: If the authentication is successful or not raise_exception is False.
60
68
 
61
69
  Raises:
62
- HTTPException: If the session is invalid.
70
+ HTTPException: If the session is invalid and raise_exception is True.
63
71
  """
64
- cookie: str = self._extract_cookie(request)
72
+ cookie: str | None = self._extract_cookie(request)
73
+ if not cookie:
74
+ return self.raise_exception(
75
+ HTTPException(
76
+ status_code=HTTPStatus.UNAUTHORIZED,
77
+ detail="Missing Credentials",
78
+ )
79
+ )
80
+
65
81
  try:
66
- session: KratosSessionObject = await kratos_service.whoami(cookie_value=cookie)
67
- except KratosSessionInvalidError as e:
68
- raise HTTPException(
69
- status_code=401,
70
- detail="Invalid Credentials",
71
- ) from e
72
- except KratosOperationError as e:
73
- raise HTTPException(
74
- status_code=500,
75
- detail="Internal Server Error",
76
- ) from e
77
-
78
- return session
82
+ self._session = await self._kratos_service.whoami(cookie_value=cookie)
83
+ except KratosSessionInvalidError:
84
+ return self.raise_exception(
85
+ HTTPException(
86
+ status_code=HTTPStatus.UNAUTHORIZED,
87
+ detail="Invalid Credentials",
88
+ )
89
+ )
90
+ except KratosOperationError:
91
+ return self.raise_exception(
92
+ HTTPException(
93
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
94
+ detail="Internal Server Error",
95
+ )
96
+ )
97
+
98
+ return
@@ -0,0 +1,20 @@
1
+ """Hydra service module."""
2
+
3
+ from .exceptions import HydraOperationError, HydraTokenInvalidError
4
+ from .objects import HydraTokenIntrospectObject
5
+ from .services import (
6
+ HydraIntrospectService,
7
+ HydraOAuth2ClientCredentialsService,
8
+ depends_hydra_introspect_service,
9
+ depends_hydra_oauth2_client_credentials_service,
10
+ )
11
+
12
+ __all__: list[str] = [
13
+ "HydraIntrospectService",
14
+ "HydraOAuth2ClientCredentialsService",
15
+ "HydraOperationError",
16
+ "HydraTokenIntrospectObject",
17
+ "HydraTokenInvalidError",
18
+ "depends_hydra_introspect_service",
19
+ "depends_hydra_oauth2_client_credentials_service",
20
+ ]
@@ -0,0 +1,15 @@
1
+ """Python exceptions for the Hydra service."""
2
+
3
+ from fastapi_factory_utilities.core.exceptions import FastAPIFactoryUtilitiesError
4
+
5
+
6
+ class HydraError(FastAPIFactoryUtilitiesError):
7
+ """Base class for all exceptions raised by the Hydra service."""
8
+
9
+
10
+ class HydraOperationError(HydraError):
11
+ """Exception raised when a Hydra operation fails."""
12
+
13
+
14
+ class HydraTokenInvalidError(HydraError):
15
+ """Exception raised when a Hydra token is invalid."""
@@ -0,0 +1,26 @@
1
+ """Provides the objects for the Hydra service."""
2
+
3
+ from typing import ClassVar
4
+
5
+ from pydantic import BaseModel, ConfigDict
6
+
7
+
8
+ class HydraTokenIntrospectObject(BaseModel):
9
+ """Represents the object returned by the Hydra token introspection."""
10
+
11
+ model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
12
+
13
+ active: bool
14
+ aud: list[str]
15
+ client_id: str
16
+ exp: int
17
+ ext: dict[str, str] | None = None
18
+ iat: int
19
+ iss: str
20
+ nbf: int
21
+ obfuscated_subject: str | None = None
22
+ scope: str
23
+ sub: str
24
+ token_type: str
25
+ token_use: str
26
+ username: str | None = None
@@ -0,0 +1,200 @@
1
+ """Provides a service to interact with the Hydra service."""
2
+
3
+ import json
4
+ from base64 import b64encode
5
+ from http import HTTPStatus
6
+ from typing import Annotated, Any, Generic, TypeVar, get_args
7
+
8
+ import aiohttp
9
+ import jwt
10
+ from fastapi import Depends
11
+ from pydantic import ValidationError
12
+
13
+ from fastapi_factory_utilities.core.app import (
14
+ DependencyConfig,
15
+ HttpServiceDependencyConfig,
16
+ depends_dependency_config,
17
+ )
18
+
19
+ from .exceptions import HydraOperationError
20
+ from .objects import HydraTokenIntrospectObject
21
+
22
+ HydraIntrospectObjectGeneric = TypeVar("HydraIntrospectObjectGeneric", bound=HydraTokenIntrospectObject)
23
+
24
+
25
+ class HydraIntrospectGenericService(Generic[HydraIntrospectObjectGeneric]):
26
+ """Service to interact with the Hydra introspect service with a generic introspect object."""
27
+
28
+ INTROSPECT_ENDPOINT: str = "/admin/oauth2/introspect"
29
+ WELLKNOWN_JWKS_ENDPOINT: str = "/.well-known/jwks.json"
30
+
31
+ def __init__(
32
+ self,
33
+ hydra_admin_http_config: HttpServiceDependencyConfig,
34
+ hydra_public_http_config: HttpServiceDependencyConfig,
35
+ ) -> None:
36
+ """Instanciate the Hydra introspect service.
37
+
38
+ Args:
39
+ hydra_admin_http_config (HttpServiceDependencyConfig): The Hydra admin HTTP configuration.
40
+ hydra_public_http_config (HttpServiceDependencyConfig): The Hydra public HTTP configuration.
41
+ """
42
+ self._hydra_admin_http_config: HttpServiceDependencyConfig = hydra_admin_http_config
43
+ self._hydra_public_http_config: HttpServiceDependencyConfig = hydra_public_http_config
44
+ # Retrieve the concrete introspect object class
45
+ generic_args: tuple[Any, ...] = get_args(self.__orig_bases__[0]) # type: ignore
46
+ self._concreate_introspect_object_class: type[HydraIntrospectObjectGeneric] = generic_args[0]
47
+
48
+ async def introspect(self, token: str) -> HydraIntrospectObjectGeneric:
49
+ """Introspects a token using the Hydra introspect service.
50
+
51
+ Args:
52
+ token (str): The token to introspect.
53
+ """
54
+ try:
55
+ async with aiohttp.ClientSession(
56
+ base_url=str(self._hydra_admin_http_config.url),
57
+ ) as session:
58
+ async with session.post(
59
+ url=self.INTROSPECT_ENDPOINT,
60
+ data={"token": token},
61
+ ) as response:
62
+ response.raise_for_status()
63
+ instrospect: HydraIntrospectObjectGeneric = self._concreate_introspect_object_class.model_validate(
64
+ await response.json()
65
+ )
66
+ except aiohttp.ClientResponseError as error:
67
+ raise HydraOperationError("Failed to introspect the token", status_code=error.status) from error
68
+ except json.JSONDecodeError as error:
69
+ raise HydraOperationError("Failed to decode the introspect response") from error
70
+ except ValidationError as error:
71
+ raise HydraOperationError("Failed to validate the introspect response") from error
72
+
73
+ return instrospect
74
+
75
+ async def get_wellknown_jwks(self) -> jwt.PyJWKSet:
76
+ """Get the JWKS from the Hydra service."""
77
+ try:
78
+ async with aiohttp.ClientSession(
79
+ base_url=str(self._hydra_public_http_config.url),
80
+ ) as session:
81
+ async with session.get(
82
+ url=self.WELLKNOWN_JWKS_ENDPOINT,
83
+ ) as response:
84
+ response.raise_for_status()
85
+ jwks_data: dict[str, Any] = await response.json()
86
+ jwks: jwt.PyJWKSet = jwt.PyJWKSet.from_dict(jwks_data)
87
+ return jwks
88
+ except aiohttp.ClientResponseError as error:
89
+ raise HydraOperationError(
90
+ "Failed to get the JWKS from the Hydra service", status_code=error.status
91
+ ) from error
92
+ except json.JSONDecodeError as error:
93
+ raise HydraOperationError("Failed to decode the JWKS from the Hydra service") from error
94
+ except ValidationError as error:
95
+ raise HydraOperationError("Failed to validate the JWKS from the Hydra service") from error
96
+
97
+
98
+ class HydraIntrospectService(HydraIntrospectGenericService[HydraTokenIntrospectObject]):
99
+ """Service to interact with the Hydra introspect service with the default HydraTokenIntrospectObject."""
100
+
101
+
102
+ class HydraOAuth2ClientCredentialsService:
103
+ """Service to interact with the Hydra service."""
104
+
105
+ INTROSPECT_ENDPOINT: str = "/admin/oauth2/introspect"
106
+ CLIENT_CREDENTIALS_ENDPOINT: str = "/oauth2/token"
107
+
108
+ def __init__(
109
+ self,
110
+ hydra_public_http_config: HttpServiceDependencyConfig,
111
+ ) -> None:
112
+ """Instanciate the Hydra service.
113
+
114
+ Args:
115
+ hydra_admin_http_config (HttpServiceDependencyConfig): The Hydra admin HTTP configuration.
116
+ hydra_public_http_config (HttpServiceDependencyConfig): The Hydra public HTTP configuration.
117
+ """
118
+ self._hydra_public_http_config: HttpServiceDependencyConfig = hydra_public_http_config
119
+
120
+ async def oauth2_client_credentials(self, client_id: str, client_secret: str, scope: str) -> str:
121
+ """Get the OAuth2 client credentials.
122
+
123
+ Args:
124
+ client_id (str): The client ID.
125
+ client_secret (str): The client secret.
126
+ scope (str): The scope.
127
+
128
+ Returns:
129
+ str: The access token.
130
+
131
+ Raises:
132
+ HydraOperationError: If the client credentials request fails.
133
+ """
134
+ # Create base64 encoded Basic Auth header
135
+ auth_string = f"{client_id}:{client_secret}"
136
+ auth_bytes = auth_string.encode("utf-8")
137
+ auth_b64 = b64encode(auth_bytes).decode("utf-8")
138
+
139
+ async with aiohttp.ClientSession(
140
+ base_url=str(self._hydra_public_http_config.url),
141
+ ) as session:
142
+ async with session.post(
143
+ url=self.CLIENT_CREDENTIALS_ENDPOINT,
144
+ headers={"Authorization": f"Basic {auth_b64}"},
145
+ data={"grant_type": "client_credentials", "scope": scope},
146
+ ) as response:
147
+ response_data = await response.json()
148
+ if response.status != HTTPStatus.OK:
149
+ raise HydraOperationError(f"Failed to get client credentials: {response_data}")
150
+
151
+ return response_data["access_token"]
152
+
153
+
154
+ def depends_hydra_oauth2_client_credentials_service(
155
+ dependency_config: Annotated[DependencyConfig, Depends(depends_dependency_config)],
156
+ ) -> HydraOAuth2ClientCredentialsService:
157
+ """Dependency injection for the Hydra OAuth2 client credentials service.
158
+
159
+ Args:
160
+ dependency_config (DependencyConfig): The dependency configuration.
161
+
162
+ Returns:
163
+ HydraOAuth2ClientCredentialsService: The Hydra OAuth2 client credentials service instance.
164
+
165
+ Raises:
166
+ HydraOperationError: If the Hydra public dependency is not configured.
167
+ """
168
+ if dependency_config.hydra_public is None:
169
+ raise HydraOperationError(message="Hydra public dependency not configured")
170
+
171
+ return HydraOAuth2ClientCredentialsService(
172
+ hydra_public_http_config=dependency_config.hydra_public,
173
+ )
174
+
175
+
176
+ def depends_hydra_introspect_service(
177
+ dependency_config: Annotated[DependencyConfig, Depends(depends_dependency_config)],
178
+ ) -> HydraIntrospectService:
179
+ """Dependency injection for the Hydra introspect service.
180
+
181
+ Args:
182
+ dependency_config (DependencyConfig): The dependency configuration.
183
+
184
+ Returns:
185
+ HydraIntrospectService: The Hydra introspect service instance.
186
+
187
+ Raises:
188
+ HydraOperationError: If the Hydra admin dependency is not configured.
189
+ """
190
+ if getattr(dependency_config, "hydra_admin", None) is None:
191
+ raise HydraOperationError(message="Hydra admin dependency not configured")
192
+ assert dependency_config.hydra_admin is not None
193
+ if getattr(dependency_config, "hydra_public", None) is None:
194
+ raise HydraOperationError(message="Hydra public dependency not configured")
195
+ assert dependency_config.hydra_public is not None
196
+
197
+ return HydraIntrospectService(
198
+ hydra_admin_http_config=dependency_config.hydra_admin,
199
+ hydra_public_http_config=dependency_config.hydra_public,
200
+ )
@@ -5,10 +5,10 @@ from .services import StatusService
5
5
  from .types import ComponentInstanceType, Status
6
6
 
7
7
  __all__: list[str] = [
8
- "ComponentTypeEnum",
9
8
  "ComponentInstanceType",
9
+ "ComponentTypeEnum",
10
10
  "HealthStatusEnum",
11
11
  "ReadinessStatusEnum",
12
- "StatusService",
13
12
  "Status",
13
+ "StatusService",
14
14
  ]
@@ -23,5 +23,5 @@ class ComponentRegistrationError(StatusServiceError):
23
23
  """
24
24
  super().__init__(
25
25
  message="An error occurred while registering the component instance.",
26
- component_instance=component_instance, # type: ignore
26
+ component_instance=component_instance,
27
27
  )
@@ -3,6 +3,7 @@
3
3
  ```python
4
4
  # Example of using the MonitoredAbstract
5
5
 
6
+
6
7
  class MyMonitored(MonitoredAbstract):
7
8
  def __init__(self, status_service: StatusService) -> None:
8
9
  super().__init__(
@@ -63,9 +64,9 @@ class MonitoredAbstract(ABC):
63
64
 
64
65
 
65
66
  __all__: list[str] = [
66
- "MonitoredAbstract",
67
67
  "ComponentInstanceType",
68
68
  "ComponentTypeEnum",
69
+ "MonitoredAbstract",
69
70
  "Status",
70
71
  "StatusService",
71
72
  ]
@@ -72,7 +72,7 @@ class YamlFileReader:
72
72
  try:
73
73
  yaml_data = yaml_data[key]
74
74
  except KeyError:
75
- logger.warning(f"Base key {key}" " not found in YAML file" + " from {self._yaml_base_key}")
75
+ logger.warning(f"Base key {key} not found in YAML file" + " from {self._yaml_base_key}")
76
76
  return dict()
77
77
  return yaml_data
78
78
 
@@ -7,7 +7,9 @@ from beanie import Document
7
7
  from fastapi_factory_utilities.core.app.application import ApplicationAbstract
8
8
  from fastapi_factory_utilities.core.app.builder import ApplicationGenericBuilder
9
9
  from fastapi_factory_utilities.core.app.config import RootConfig
10
- from fastapi_factory_utilities.core.plugins import PluginsEnum
10
+ from fastapi_factory_utilities.core.plugins.abstracts import PluginAbstract
11
+ from fastapi_factory_utilities.core.plugins.odm_plugin import ODMPlugin
12
+ from fastapi_factory_utilities.core.plugins.opentelemetry_plugin import OpenTelemetryPlugin
11
13
  from fastapi_factory_utilities.example.models.books.document import BookDocument
12
14
 
13
15
 
@@ -26,12 +28,11 @@ class App(ApplicationAbstract):
26
28
 
27
29
  ODM_DOCUMENT_MODELS: ClassVar[list[type[Document]]] = [BookDocument]
28
30
 
29
- DEFAULT_PLUGINS_ACTIVATED: ClassVar[list[PluginsEnum]] = [PluginsEnum.OPENTELEMETRY_PLUGIN, PluginsEnum.ODM_PLUGIN]
30
-
31
31
  def configure(self) -> None:
32
32
  """Configure the application."""
33
33
  # Prevent circular import
34
- from .api import api_router # pylint: disable=import-outside-toplevel
34
+ # pylint: disable=import-outside-toplevel
35
+ from .api import api_router # noqa: PLC0415
35
36
 
36
37
  self.get_asgi_app().include_router(router=api_router)
37
38
 
@@ -47,4 +48,13 @@ class App(ApplicationAbstract):
47
48
  class AppBuilder(ApplicationGenericBuilder[App]):
48
49
  """Application builder for the App application."""
49
50
 
50
- pass
51
+ def get_default_plugins(self) -> list[PluginAbstract]:
52
+ """Get the default plugins."""
53
+ return [ODMPlugin(), OpenTelemetryPlugin()]
54
+
55
+ def __init__(self, plugins: list[PluginAbstract] | None = None) -> None:
56
+ """Initialize the AppBuilder."""
57
+ # If no plugins are provided, use the default plugins
58
+ if plugins is None:
59
+ plugins = self.get_default_plugins()
60
+ super().__init__(plugins=plugins)
@@ -4,4 +4,4 @@ from .entities import BookEntity
4
4
  from .enums import BookType
5
5
  from .types import BookName
6
6
 
7
- __all__: list[str] = ["BookEntity", "BookType", "BookName"]
7
+ __all__: list[str] = ["BookEntity", "BookName", "BookType"]
@@ -3,4 +3,4 @@
3
3
  from .document import BookDocument
4
4
  from .repository import BookRepository
5
5
 
6
- __all__: list[str] = ["BookRepository", "BookDocument"]
6
+ __all__: list[str] = ["BookDocument", "BookRepository"]
@@ -1,9 +1,10 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: fastapi_factory_utilities
3
- Version: 0.3.3
4
- Summary: Consolidate libraries and utilities to create microservices in Python with FastAPI, Beanie, Httpx, AioPika and OpenTelemetry.
3
+ Version: 0.8.2
4
+ Summary: Consolidate libraries and utilities to create microservices in Python with FastAPI, Beanie, Taskiq, AioPika and OpenTelemetry.
5
5
  License: MIT
6
- Keywords: python,fastapi,beanie,httpx,opentelemetry,microservices
6
+ License-File: LICENSE
7
+ Keywords: python,fastapi,beanie,taskiq,opentelemetry,microservices
7
8
  Author: miragecentury
8
9
  Author-email: victorien.vanroye@gmail.com
9
10
  Maintainer: miragecentury
@@ -18,26 +19,31 @@ Classifier: Programming Language :: Python :: 3.12
18
19
  Classifier: Topic :: Software Development :: Libraries
19
20
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
20
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
- Requires-Dist: aiohttp[speedups] (>=3.11.16,<4.0.0)
22
- Requires-Dist: beanie (>=1.27.0,<2.0.0)
23
- Requires-Dist: fastapi (>=0.115.4,<0.116.0)
24
- Requires-Dist: httpx (>=0.28.1,<0.29.0)
22
+ Requires-Dist: aio-pika (>=9.5.7,<10.0.0)
23
+ Requires-Dist: aiohttp[speedups] (>=3.12.13,<4.0.0)
24
+ Requires-Dist: beanie (>=1.30.0,<2.0.0)
25
+ Requires-Dist: fastapi (>=0.115.13,<1)
25
26
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc (>=1.26.0,<2.0.0)
26
27
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.26.0,<2.0.0)
27
- Requires-Dist: opentelemetry-instrumentation-fastapi (>=0.49b1,<0.50)
28
- Requires-Dist: opentelemetry-instrumentation-pymongo (>=0.49b2,<0.50)
28
+ Requires-Dist: opentelemetry-instrumentation-aio-pika (>=0.59b0,<0.60)
29
+ Requires-Dist: opentelemetry-instrumentation-aiohttp-client (>=0,<1)
30
+ Requires-Dist: opentelemetry-instrumentation-fastapi (>=0,<1)
31
+ Requires-Dist: opentelemetry-instrumentation-pymongo (>=0,<1)
29
32
  Requires-Dist: opentelemetry-propagator-b3 (>=1.26.0,<2.0.0)
30
33
  Requires-Dist: opentelemetry-sdk (>=1.26.0,<2.0.0)
31
34
  Requires-Dist: pyaml (>=25.1.0,<26.0.0)
32
35
  Requires-Dist: pydantic (>=2.8.2,<3.0.0)
33
36
  Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
34
- Requires-Dist: pymongo (>=4.9.2,<4.10.0)
37
+ Requires-Dist: pymongo (>=4.9.2,<4.16.0)
35
38
  Requires-Dist: reactivex (>=4.0.4,<5.0.0)
36
39
  Requires-Dist: structlog (>=24.1,<26.0)
37
- Requires-Dist: typer (>=0.15.1,<0.16.0)
38
- Requires-Dist: uvicorn (>=0.32.0,<0.33.0)
39
- Project-URL: Homepage, https://github.com/miragecentury/fastapi_factory_utilities
40
- Project-URL: Repository, https://github.com/miragecentury/fastapi_factory_utilities
40
+ Requires-Dist: taskiq-dependencies (>=1.5.8,<2.0.0)
41
+ Requires-Dist: taskiq-fastapi (>=0.3.5,<0.4.0)
42
+ Requires-Dist: taskiq-redis (>=1.0.9,<2.0.0)
43
+ Requires-Dist: typer (>=0,<1)
44
+ Requires-Dist: uvicorn (>=0.34.3,<1)
45
+ Project-URL: Homepage, https://github.com/DeerHide/fastapi_factory_utilities
46
+ Project-URL: Repository, https://github.com/DeerHide/fastapi_factory_utilities
41
47
  Description-Content-Type: text/markdown
42
48
 
43
49
  # fastapi_factory_utilities