fastapi-factory-utilities 0.4.0__py3-none-any.whl → 0.7.1__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.

Potentially problematic release.


This version of fastapi-factory-utilities might be problematic. Click here for more details.

Files changed (56) 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 +8 -32
  6. fastapi_factory_utilities/core/app/fastapi_builder.py +3 -2
  7. fastapi_factory_utilities/core/exceptions.py +55 -28
  8. fastapi_factory_utilities/core/plugins/__init__.py +2 -31
  9. fastapi_factory_utilities/core/plugins/abstracts.py +40 -0
  10. fastapi_factory_utilities/core/plugins/aiopika/__init__.py +25 -0
  11. fastapi_factory_utilities/core/plugins/aiopika/abstract.py +48 -0
  12. fastapi_factory_utilities/core/plugins/aiopika/configs.py +85 -0
  13. fastapi_factory_utilities/core/plugins/aiopika/depends.py +20 -0
  14. fastapi_factory_utilities/core/plugins/aiopika/exceptions.py +29 -0
  15. fastapi_factory_utilities/core/plugins/aiopika/exchange.py +70 -0
  16. fastapi_factory_utilities/core/plugins/aiopika/listener/__init__.py +7 -0
  17. fastapi_factory_utilities/core/plugins/aiopika/listener/abstract.py +72 -0
  18. fastapi_factory_utilities/core/plugins/aiopika/message.py +86 -0
  19. fastapi_factory_utilities/core/plugins/aiopika/plugins.py +84 -0
  20. fastapi_factory_utilities/core/plugins/aiopika/publisher/__init__.py +7 -0
  21. fastapi_factory_utilities/core/plugins/aiopika/publisher/abstract.py +66 -0
  22. fastapi_factory_utilities/core/plugins/aiopika/queue.py +86 -0
  23. fastapi_factory_utilities/core/plugins/odm_plugin/__init__.py +14 -157
  24. fastapi_factory_utilities/core/plugins/odm_plugin/builder.py +3 -3
  25. fastapi_factory_utilities/core/plugins/odm_plugin/configs.py +1 -1
  26. fastapi_factory_utilities/core/plugins/odm_plugin/documents.py +1 -1
  27. fastapi_factory_utilities/core/plugins/odm_plugin/helpers.py +16 -0
  28. fastapi_factory_utilities/core/plugins/odm_plugin/plugins.py +155 -0
  29. fastapi_factory_utilities/core/plugins/odm_plugin/repositories.py +1 -0
  30. fastapi_factory_utilities/core/plugins/opentelemetry_plugin/__init__.py +8 -121
  31. fastapi_factory_utilities/core/plugins/opentelemetry_plugin/instruments/__init__.py +85 -0
  32. fastapi_factory_utilities/core/plugins/opentelemetry_plugin/plugins.py +137 -0
  33. fastapi_factory_utilities/core/plugins/taskiq_plugins/__init__.py +29 -0
  34. fastapi_factory_utilities/core/plugins/taskiq_plugins/configs.py +12 -0
  35. fastapi_factory_utilities/core/plugins/taskiq_plugins/depends.py +51 -0
  36. fastapi_factory_utilities/core/plugins/taskiq_plugins/exceptions.py +13 -0
  37. fastapi_factory_utilities/core/plugins/taskiq_plugins/plugin.py +41 -0
  38. fastapi_factory_utilities/core/plugins/taskiq_plugins/schedulers.py +187 -0
  39. fastapi_factory_utilities/core/protocols.py +1 -54
  40. fastapi_factory_utilities/core/security/jwt.py +6 -5
  41. fastapi_factory_utilities/core/services/status/__init__.py +2 -2
  42. fastapi_factory_utilities/core/utils/status.py +2 -1
  43. fastapi_factory_utilities/core/utils/yaml_reader.py +1 -1
  44. fastapi_factory_utilities/example/app.py +15 -5
  45. fastapi_factory_utilities/example/entities/books/__init__.py +1 -1
  46. fastapi_factory_utilities/example/models/books/__init__.py +1 -1
  47. {fastapi_factory_utilities-0.4.0.dist-info → fastapi_factory_utilities-0.7.1.dist-info}/METADATA +14 -8
  48. {fastapi_factory_utilities-0.4.0.dist-info → fastapi_factory_utilities-0.7.1.dist-info}/RECORD +51 -32
  49. {fastapi_factory_utilities-0.4.0.dist-info → fastapi_factory_utilities-0.7.1.dist-info}/WHEEL +1 -1
  50. fastapi_factory_utilities/core/app/plugin_manager/__init__.py +0 -15
  51. fastapi_factory_utilities/core/app/plugin_manager/exceptions.py +0 -33
  52. fastapi_factory_utilities/core/app/plugin_manager/plugin_manager.py +0 -190
  53. fastapi_factory_utilities/core/plugins/example/__init__.py +0 -31
  54. fastapi_factory_utilities/core/plugins/httpx_plugin/__init__.py +0 -31
  55. {fastapi_factory_utilities-0.4.0.dist-info → fastapi_factory_utilities-0.7.1.dist-info}/entry_points.txt +0 -0
  56. {fastapi_factory_utilities-0.4.0.dist-info → fastapi_factory_utilities-0.7.1.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,13 @@
1
+ """Provides the exceptions for the Taskiq plugin."""
2
+
3
+ from typing import Any
4
+
5
+ from fastapi_factory_utilities.core.exceptions import FastAPIFactoryUtilitiesError
6
+
7
+
8
+ class TaskiqPluginBaseError(FastAPIFactoryUtilitiesError):
9
+ """Base class for all exceptions raised by the Taskiq plugin."""
10
+
11
+ def __init__(self, message: str, **kwargs: Any) -> None:
12
+ """Initialize the Taskiq plugin base exception."""
13
+ super().__init__(message, **kwargs)
@@ -0,0 +1,41 @@
1
+ """Provides the Taskiq plugin."""
2
+
3
+ from collections.abc import Callable
4
+
5
+ from fastapi_factory_utilities.core.plugins.abstracts import PluginAbstract
6
+
7
+ from .configs import RedisCredentialsConfig
8
+ from .depends import DEPENDS_SCHEDULER_COMPONENT_KEY
9
+ from .schedulers import SchedulerComponent
10
+
11
+
12
+ class TaskiqPlugin(PluginAbstract):
13
+ """Taskiq plugin."""
14
+
15
+ def __init__(
16
+ self, redis_credentials_config: RedisCredentialsConfig, register_hook: Callable[[SchedulerComponent], None]
17
+ ) -> None:
18
+ """Initialize the Taskiq plugin."""
19
+ super().__init__()
20
+ self._redis_credentials_config: RedisCredentialsConfig = redis_credentials_config
21
+ self._register_hook: Callable[[SchedulerComponent], None] = register_hook
22
+ self._scheduler_component: SchedulerComponent = SchedulerComponent()
23
+
24
+ def on_load(self) -> None:
25
+ """On load."""
26
+ assert self._application is not None
27
+ self._scheduler_component.configure(
28
+ redis_connection_string=self._redis_credentials_config.url, app=self._application.get_asgi_app()
29
+ )
30
+ self._add_to_state(key=DEPENDS_SCHEDULER_COMPONENT_KEY, value=self._scheduler_component)
31
+ self._register_hook(self._scheduler_component)
32
+
33
+ async def on_startup(self) -> None:
34
+ """On startup."""
35
+ assert self._application is not None
36
+ await self._scheduler_component.startup(app=self._application.get_asgi_app())
37
+
38
+ async def on_shutdown(self) -> None:
39
+ """On shutdown."""
40
+ assert self._application is not None
41
+ await self._scheduler_component.shutdown()
@@ -0,0 +1,187 @@
1
+ """Scheduler module for fastapi_factory_utilities.
2
+
3
+ This module provides components and utilities for scheduling tasks using Taskiq, FastAPI, and Redis.
4
+ It enables registration, configuration, and management of scheduled tasks in FastAPI applications.
5
+ """
6
+
7
+ import asyncio
8
+ from collections.abc import Coroutine
9
+ from typing import Any, Self, cast
10
+
11
+ import taskiq_fastapi
12
+ from fastapi import FastAPI
13
+ from structlog.stdlib import get_logger
14
+ from taskiq import (
15
+ AsyncBroker,
16
+ AsyncTaskiqDecoratedTask,
17
+ ScheduleSource,
18
+ TaskiqScheduler,
19
+ )
20
+ from taskiq.api import run_receiver_task, run_scheduler_task
21
+ from taskiq.scheduler.created_schedule import CreatedSchedule
22
+ from taskiq.scheduler.scheduled_task import ScheduledTask
23
+ from taskiq_redis import (
24
+ ListRedisScheduleSource,
25
+ RedisAsyncResultBackend,
26
+ RedisStreamBroker,
27
+ )
28
+
29
+ _logger = get_logger(__package__)
30
+
31
+
32
+ class SchedulerComponent:
33
+ """Scheduler component."""
34
+
35
+ NAME_SUFFIX: str = "tiktok_integration"
36
+
37
+ def __init__(self) -> None:
38
+ """Initialize the scheduler component."""
39
+ self._result_backend: RedisAsyncResultBackend[Any] | None = None
40
+ self._stream_broker: RedisStreamBroker | None = None
41
+ self._scheduler: TaskiqScheduler | None = None
42
+ self._scheduler_source: ListRedisScheduleSource | None = None
43
+ self._dyn_task: AsyncTaskiqDecoratedTask[Any, Any] | None = None
44
+ self._schedule_cron: ScheduledTask | None = None
45
+ self._schedulers_tasks: dict[str, AsyncTaskiqDecoratedTask[Any, Any]] = {}
46
+
47
+ def register_task(self, task: Coroutine[Any, Any, Any], task_name: str) -> None:
48
+ """Register a task.
49
+
50
+ Args:
51
+ task: The task to register.
52
+ task_name: The name of the task.
53
+
54
+ Raises:
55
+ ValueError: If the task is already registered.
56
+ ValueError: If the stream broker is not initialized.
57
+ """
58
+ if self._stream_broker is None:
59
+ raise ValueError("Stream broker is not initialized")
60
+
61
+ if task_name in self._schedulers_tasks:
62
+ raise ValueError(f"Task {task_name} already registered")
63
+
64
+ self._schedulers_tasks[task_name] = self._stream_broker.register_task(task, task_name) # type: ignore
65
+
66
+ def get_task(self, task_name: str) -> AsyncTaskiqDecoratedTask[Any, Any]:
67
+ """Get a task.
68
+
69
+ Args:
70
+ task_name: The name of the task.
71
+
72
+ Returns:
73
+ AsyncTaskiqDecoratedTask: The task.
74
+
75
+ Raises:
76
+ ValueError: If the task is not registered.
77
+ """
78
+ if task_name not in self._schedulers_tasks:
79
+ raise ValueError(f"Task {task_name} not registered")
80
+ return self._schedulers_tasks[task_name]
81
+
82
+ def configure(self, redis_connection_string: str, app: FastAPI) -> Self:
83
+ """Configure the scheduler component."""
84
+ self._result_backend = RedisAsyncResultBackend(
85
+ redis_url=redis_connection_string,
86
+ prefix_str=f"velmios_taskiq_result_backend_{self.NAME_SUFFIX}",
87
+ result_ex_time=120,
88
+ )
89
+ self._stream_broker = RedisStreamBroker(
90
+ url=redis_connection_string,
91
+ queue_name=f"velmios_taskiq_stream_broker_{self.NAME_SUFFIX}",
92
+ consumer_group_name=f"velmios_taskiq_consumer_group_{self.NAME_SUFFIX}",
93
+ ).with_result_backend(self._result_backend)
94
+
95
+ taskiq_fastapi.populate_dependency_context(self._stream_broker, app)
96
+
97
+ self._scheduler_source = ListRedisScheduleSource(
98
+ url=redis_connection_string,
99
+ prefix=f"velmios_taskiq_schedule_source_{self.NAME_SUFFIX}",
100
+ )
101
+
102
+ self._scheduler = TaskiqScheduler(
103
+ broker=self._stream_broker,
104
+ sources=[self._scheduler_source],
105
+ )
106
+
107
+ return self
108
+
109
+ async def startup(self, app: FastAPI) -> None:
110
+ """Start the scheduler."""
111
+ if self._result_backend is None:
112
+ raise ValueError("Result backend is not initialized")
113
+ if self._stream_broker is None:
114
+ raise ValueError("Stream broker is not initialized")
115
+ if self._scheduler is None:
116
+ raise ValueError("Scheduler is not initialized")
117
+ if self._scheduler_source is None:
118
+ raise ValueError("Scheduler source is not initialized")
119
+
120
+ _logger.info("Starting scheduler")
121
+ await self._result_backend.startup()
122
+ await self._stream_broker.startup()
123
+ await self._scheduler.startup()
124
+ _logger.info("Scheduler started")
125
+ _logger.info("Scheduling task")
126
+ schedules: list[ScheduledTask] = await self._scheduler_source.get_schedules()
127
+ _logger.info("Schedules retrieved", schedules=schedules)
128
+
129
+ self._schedule_cron = next(filter(lambda x: x.task_name == "heartbeat", schedules), None)
130
+
131
+ if self._schedule_cron is None:
132
+ _logger.info("No schedules found, scheduling task")
133
+ self._dyn_task = self.get_task("heartbeat")
134
+ task_created: CreatedSchedule[Any] = await self._dyn_task.schedule_by_cron(
135
+ source=self._scheduler_source, cron="* * * * *", msg="every minute"
136
+ )
137
+ self._schedule_cron = task_created.task
138
+ _logger.info("Task scheduled")
139
+ else:
140
+ _logger.info("Schedules found, skipping scheduling")
141
+
142
+ _logger.info("Starting worker and scheduler tasks")
143
+ taskiq_fastapi.populate_dependency_context(self._stream_broker, app, app.state) # type: ignore
144
+ self._worker_task: asyncio.Task[None] = asyncio.create_task(run_receiver_task(self._stream_broker))
145
+ self._scheduler_task: asyncio.Task[None] = asyncio.create_task(run_scheduler_task(self._scheduler))
146
+ _logger.info("Worker and scheduler tasks started")
147
+
148
+ async def shutdown(self) -> None:
149
+ """Stop the scheduler."""
150
+ _logger.info("Stopping worker")
151
+ self._worker_task.cancel()
152
+ self._scheduler_task.cancel()
153
+ try:
154
+ await self._worker_task
155
+ except (asyncio.CancelledError, RuntimeError) as e:
156
+ _logger.info("Worker task cancelled", error=e)
157
+ try:
158
+ await self._scheduler_task
159
+ except (asyncio.CancelledError, RuntimeError) as e:
160
+ _logger.info("Scheduler task cancelled", error=e)
161
+
162
+ while not self._worker_task.done() or not self._scheduler_task.done():
163
+ await asyncio.sleep(0.1)
164
+
165
+ _logger.info("Stopping scheduler")
166
+ if self._scheduler is not None:
167
+ await self._scheduler.shutdown()
168
+ if self._stream_broker is not None:
169
+ await self._stream_broker.shutdown()
170
+ if self._result_backend is not None:
171
+ await self._result_backend.shutdown()
172
+ _logger.info("Scheduler stopped")
173
+
174
+ @property
175
+ def scheduler(self) -> TaskiqScheduler:
176
+ """Get the scheduler."""
177
+ return cast(TaskiqScheduler, self._scheduler)
178
+
179
+ @property
180
+ def broker(self) -> AsyncBroker:
181
+ """Get the broker."""
182
+ return cast(AsyncBroker, self._stream_broker)
183
+
184
+ @property
185
+ def scheduler_source(self) -> ScheduleSource:
186
+ """Get the scheduler source."""
187
+ return cast(ScheduleSource, self._scheduler_source)
@@ -1,17 +1,15 @@
1
1
  """Protocols for the base application."""
2
2
 
3
3
  from abc import abstractmethod
4
- from typing import TYPE_CHECKING, ClassVar, Protocol, runtime_checkable
4
+ from typing import TYPE_CHECKING, ClassVar, Protocol
5
5
 
6
6
  from beanie import Document
7
7
  from fastapi import FastAPI
8
8
 
9
- from fastapi_factory_utilities.core.plugins import PluginsEnum
10
9
  from fastapi_factory_utilities.core.services.status.services import StatusService
11
10
 
12
11
  if TYPE_CHECKING:
13
12
  from fastapi_factory_utilities.core.app.config import RootConfig
14
- from fastapi_factory_utilities.core.plugins import PluginState
15
13
 
16
14
 
17
15
  class ApplicationAbstractProtocol(Protocol):
@@ -21,8 +19,6 @@ class ApplicationAbstractProtocol(Protocol):
21
19
 
22
20
  ODM_DOCUMENT_MODELS: ClassVar[list[type[Document]]]
23
21
 
24
- DEFAULT_PLUGINS_ACTIVATED: ClassVar[list[PluginsEnum]]
25
-
26
22
  @abstractmethod
27
23
  def get_config(self) -> "RootConfig":
28
24
  """Get the application configuration."""
@@ -34,52 +30,3 @@ class ApplicationAbstractProtocol(Protocol):
34
30
  @abstractmethod
35
31
  def get_status_service(self) -> StatusService:
36
32
  """Get the status service."""
37
-
38
-
39
- @runtime_checkable
40
- class PluginProtocol(Protocol):
41
- """Defines the protocol for the plugins."""
42
-
43
- @abstractmethod
44
- def pre_conditions_check(self, application: ApplicationAbstractProtocol) -> bool:
45
- """Check the pre-conditions for the plugin.
46
-
47
- Args:
48
- application (BaseApplicationProtocol): The application.
49
-
50
- Returns:
51
- bool: True if the pre-conditions are met, False otherwise.
52
- """
53
-
54
- @abstractmethod
55
- def on_load(self, application: ApplicationAbstractProtocol) -> list["PluginState"] | None:
56
- """The actions to perform on load for the plugin.
57
-
58
- Args:
59
- application (BaseApplicationProtocol): The application.
60
-
61
- Returns:
62
- None
63
- """
64
-
65
- @abstractmethod
66
- async def on_startup(self, application: ApplicationAbstractProtocol) -> list["PluginState"] | None:
67
- """The actions to perform on startup for the plugin.
68
-
69
- Args:
70
- application (BaseApplicationProtocol): The application.
71
-
72
- Returns:
73
- None
74
- """
75
-
76
- @abstractmethod
77
- async def on_shutdown(self, application: ApplicationAbstractProtocol) -> None:
78
- """The actions to perform on shutdown for the plugin.
79
-
80
- Args:
81
- application (BaseApplicationProtocol): The application.
82
-
83
- Returns:
84
- None
85
- """
@@ -140,11 +140,12 @@ class JWTBearerAuthentication:
140
140
  # by the request or by the jwt parameter
141
141
  if self.jwt_raw is None and request is None:
142
142
  raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail="Missing Credentials")
143
- jwt_raw: str = (
144
- self.jwt_raw
145
- if self.jwt_raw is not None
146
- else self._extract_raw_token(request=request) # type: ignore[arg-type]
147
- )
143
+ jwt_raw: str
144
+ if self.jwt_raw is None:
145
+ jwt_raw = self._extract_raw_token(request=request) # type: ignore[arg-type]
146
+ else:
147
+ jwt_raw = self.jwt_raw
148
+
148
149
  # Execute the io bound and cpu bound tasks in parallel
149
150
  async with TaskGroup() as tg:
150
151
  # TODO: Can be disabled by configuration (for operation purposes)
@@ -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
  ]
@@ -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.4.0
4
- Summary: Consolidate libraries and utilities to create microservices in Python with FastAPI, Beanie, Httpx, AioPika and OpenTelemetry.
3
+ Version: 0.7.1
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,12 +19,14 @@ 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
22
+ Requires-Dist: aio-pika (>=9.5.7,<10.0.0)
21
23
  Requires-Dist: aiohttp[speedups] (>=3.12.13,<4.0.0)
22
24
  Requires-Dist: beanie (>=1.30.0,<2.0.0)
23
25
  Requires-Dist: fastapi (>=0.115.13,<1)
24
26
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc (>=1.26.0,<2.0.0)
25
27
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.26.0,<2.0.0)
26
- Requires-Dist: opentelemetry-instrumentation-aiohttp-client (>=0.55b1,<0.56)
28
+ Requires-Dist: opentelemetry-instrumentation-aio-pika (>=0.59b0,<0.60)
29
+ Requires-Dist: opentelemetry-instrumentation-aiohttp-client (>=0,<1)
27
30
  Requires-Dist: opentelemetry-instrumentation-fastapi (>=0,<1)
28
31
  Requires-Dist: opentelemetry-instrumentation-pymongo (>=0,<1)
29
32
  Requires-Dist: opentelemetry-propagator-b3 (>=1.26.0,<2.0.0)
@@ -31,13 +34,16 @@ 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)
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)
37
43
  Requires-Dist: typer (>=0,<1)
38
44
  Requires-Dist: uvicorn (>=0.34.3,<1)
39
- Project-URL: Homepage, https://github.com/miragecentury/fastapi_factory_utilities
40
- Project-URL: Repository, https://github.com/miragecentury/fastapi_factory_utilities
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
@@ -1,38 +1,57 @@
1
1
  fastapi_factory_utilities/__main__.py,sha256=w8o9KpyHcxGyLHmTK8ixbIqJIsB3NbIGuAMY7OfnxrA,147
2
2
  fastapi_factory_utilities/core/__init__.py,sha256=tt5a-MgeFt_oACkc9K5xl2rynIbca9DGqsKBDEqGzto,34
3
- fastapi_factory_utilities/core/api/__init__.py,sha256=eehUFVDPk07MUPIorGdC8WqDRB8NjdSy7Za55CdLrps,542
3
+ fastapi_factory_utilities/core/api/__init__.py,sha256=fAwgRcRry1nIyAL7CsCbpwR87n5tWnBWKEPH6QZCpp8,542
4
4
  fastapi_factory_utilities/core/api/tags.py,sha256=3hQcTeW0FS78sPTJ2PB44dMDTSkoW-xKj7rrfKX2Lk0,154
5
5
  fastapi_factory_utilities/core/api/v1/sys/__init__.py,sha256=mTXhpn3_KgQ1snt0-0PFmGvFr4n5srQRRADEdRSGFJM,345
6
- fastapi_factory_utilities/core/api/v1/sys/health.py,sha256=IF51Z1seOFn91m3FC57U8uWfAA7c_EhhBpjbu_ly9WQ,2807
6
+ fastapi_factory_utilities/core/api/v1/sys/health.py,sha256=LILUwfyqeBDlf4GSpkU_3bxMjZPCLanOBkMGDKtQufY,2867
7
7
  fastapi_factory_utilities/core/api/v1/sys/readiness.py,sha256=xIY8pQLShU7KWRtlOUK5gTDyZ8aB1KBvLczC6boT-tg,1711
8
- fastapi_factory_utilities/core/app/__init__.py,sha256=IHHkcu3t-fX8vxQk12A36cE-yTjGn_PInDpL_OlRSE8,596
9
- fastapi_factory_utilities/core/app/application.py,sha256=WrDXh00r_jzQTtZGeFO43lIzvDraplitejTaSJj_uFE,5091
10
- fastapi_factory_utilities/core/app/builder.py,sha256=XKtJuRxvaqzNdhfNXGkyyxEH4MkZCgAUjkqYnOws8n0,4728
8
+ fastapi_factory_utilities/core/app/__init__.py,sha256=6Ee_zK-KzJWoOElsAnGdBz8giRJlhAPMaEzs0I3gvrA,596
9
+ fastapi_factory_utilities/core/app/application.py,sha256=fJTKgfqBWD1xzE7Y9ToZEBDrd1PxHtnZ7SHLmkS1S1M,4737
10
+ fastapi_factory_utilities/core/app/builder.py,sha256=gkmhGVYFu2zbW5sxWyh6Pn5ysdCIvn1_WqNJMKls54s,3820
11
11
  fastapi_factory_utilities/core/app/config.py,sha256=MuV4G_M4QgZWYHoulusJLv_m4Qr2php-Cg9Jum4qkNA,7303
12
12
  fastapi_factory_utilities/core/app/enums.py,sha256=X1upnaehYU0eHExXTde5xsH-pI9q7HZDNsOEF5PApdg,226
13
13
  fastapi_factory_utilities/core/app/exceptions.py,sha256=tQDf0_4j5xgCbku7TL7JaZGs3_bjsWG2YLBCydQJpPw,664
14
- fastapi_factory_utilities/core/app/fastapi_builder.py,sha256=DgIqiCnJK6cqsG-sg4H7Pi0lkhaxOhSLQt_ksHjpjW0,2835
15
- fastapi_factory_utilities/core/app/plugin_manager/__init__.py,sha256=eMfxCsk41Caw_juAawmDZHhytNI_ubXmqfRDug2AzvQ,319
16
- fastapi_factory_utilities/core/app/plugin_manager/exceptions.py,sha256=CFrZvROT7mLzNpXWwDra1j08lA_7ZrSrOHN94sEEfnQ,1026
17
- fastapi_factory_utilities/core/app/plugin_manager/plugin_manager.py,sha256=5E_Qp535xNJHNujZ_QRiMfIkDUy9F_3Rbjlclny5P08,6682
18
- fastapi_factory_utilities/core/exceptions.py,sha256=HAd0RDJNBVc1NOcwfHQo_Xya8SCYuD9edynx3VKMYVs,1784
19
- fastapi_factory_utilities/core/plugins/__init__.py,sha256=W-BCkqP0xG980980z3mc8T6Vrp1Akv4szA0PRzkUbiU,756
20
- fastapi_factory_utilities/core/plugins/example/__init__.py,sha256=GF69IygLXxzrCh7VryekEWun663kKBhWtRS3w-1tzBc,1030
21
- fastapi_factory_utilities/core/plugins/httpx_plugin/__init__.py,sha256=P5FUyv7mQr8RZWQ8ifkoK8GXvqSI71q2b2dm-ag2JhQ,1028
22
- fastapi_factory_utilities/core/plugins/odm_plugin/__init__.py,sha256=L6iZW7beZLpvXbcXoTjP6iALEwWWymworb6Mok72s2w,5741
23
- fastapi_factory_utilities/core/plugins/odm_plugin/builder.py,sha256=Wf9Geo2ayCX9no8ENJcsfLRo-zrAuZFfUJkvnb01PRk,8759
24
- fastapi_factory_utilities/core/plugins/odm_plugin/configs.py,sha256=zQoJC1wLNyq2pZyFhl0bKeNsTl4y_4_82BHCCaOEjCQ,331
14
+ fastapi_factory_utilities/core/app/fastapi_builder.py,sha256=7egWkS98nTiVBe2Bw5dQzDBryQCkz4w7gnY9HA24NFg,2855
15
+ fastapi_factory_utilities/core/exceptions.py,sha256=9s-i_RHPCsOswQPRvK8tyy-smE1118pytxWDJMNEl0M,2670
16
+ fastapi_factory_utilities/core/plugins/__init__.py,sha256=7ctIv2Jx2uOUpgm8ITFRuZxHi6OXvlVS0VcbszVzvis,114
17
+ fastapi_factory_utilities/core/plugins/abstracts.py,sha256=p5iXmeOVD737G73I2keKV0Y-jLGQf2vYbTSR1LgrA14,1165
18
+ fastapi_factory_utilities/core/plugins/aiopika/__init__.py,sha256=flXanbhbjFaOsgx7jZvtW0bVLT_NXHypIPFO1tIHoCM,705
19
+ fastapi_factory_utilities/core/plugins/aiopika/abstract.py,sha256=TcvDwdaLV0UqFHQy6Sn3Y5Fp-1463dhL7VNB9LTKL5I,1682
20
+ fastapi_factory_utilities/core/plugins/aiopika/configs.py,sha256=BEPE8Ss7q_yCyuii4nywmIgh67iNLdhKxUm8tC0PdCY,3706
21
+ fastapi_factory_utilities/core/plugins/aiopika/depends.py,sha256=5xna571hCIdqzbo0t1CW-yzmJMSpEw_KUeJh5nBXjwQ,761
22
+ fastapi_factory_utilities/core/plugins/aiopika/exceptions.py,sha256=AkBKT8HVPpJDAntLNlOLp6lpQpKI-k8gxNzU24FsOF0,985
23
+ fastapi_factory_utilities/core/plugins/aiopika/exchange.py,sha256=tQfrv7-mX4lrHY1OTXB_aTkbg_brYniIuFisfFDSTT8,2509
24
+ fastapi_factory_utilities/core/plugins/aiopika/listener/__init__.py,sha256=LsTyu6kGoUm7c5OvSQTDJL7d8CG9TeARBHHVe_HGsHY,148
25
+ fastapi_factory_utilities/core/plugins/aiopika/listener/abstract.py,sha256=cMRQwqCwa1kGs2PHXR5ws0-HLzqHC_XFZtu43Y7iTpA,2577
26
+ fastapi_factory_utilities/core/plugins/aiopika/message.py,sha256=Tn9pLZlkx238GA6SEav15Npq3TWu_dQ0NtzFWvPcPTM,2861
27
+ fastapi_factory_utilities/core/plugins/aiopika/plugins.py,sha256=0lLYt-ZG3g3m8wi1tCCPEhTUBqaXuEJOwHEcrvP7FYc,3284
28
+ fastapi_factory_utilities/core/plugins/aiopika/publisher/__init__.py,sha256=MGGdygH72xHZ4QAwvbUZKQt-_mPzLmMxHyAACSNnZ_c,151
29
+ fastapi_factory_utilities/core/plugins/aiopika/publisher/abstract.py,sha256=PmIG5zlx-tFUAneHtbknR0Ik5flz8pMTzxcreY2hZ7s,2494
30
+ fastapi_factory_utilities/core/plugins/aiopika/queue.py,sha256=u7iOOnv8EHO7q2qM6jDlYimajrjlQN8R3ftL61XgQIE,2794
31
+ fastapi_factory_utilities/core/plugins/odm_plugin/__init__.py,sha256=JsVz4GBiZRmm4qpUD1-Wsg2tRXTn-VO5fU-W1whZo4E,683
32
+ fastapi_factory_utilities/core/plugins/odm_plugin/builder.py,sha256=MdO1D0C9LQpoqtNFqgPwSYedLzXR6PArhkoJw6wzykg,8761
33
+ fastapi_factory_utilities/core/plugins/odm_plugin/configs.py,sha256=5bVbtsLwJhuIvt8FCzOvk002G8qFmZumWkN75bPKatc,331
25
34
  fastapi_factory_utilities/core/plugins/odm_plugin/depends.py,sha256=OcLsfTLzMBk_xFV6qsMy_-qFkiphEbbEuaHUooagxg8,730
26
- fastapi_factory_utilities/core/plugins/odm_plugin/documents.py,sha256=BFQYHxHBmTacJRfhZi2OffvT_RAFvAAiDVQAa_d6Y7w,1141
35
+ fastapi_factory_utilities/core/plugins/odm_plugin/documents.py,sha256=4aQNrD26d0S542_LYmxxm07Q8SWzbGe3PCpho6iWY5Q,1102
27
36
  fastapi_factory_utilities/core/plugins/odm_plugin/exceptions.py,sha256=acnKJB0lGAzDs-7-LjBap8shjP3iV1a7dw7ouPVF27o,551
28
- fastapi_factory_utilities/core/plugins/odm_plugin/repositories.py,sha256=pOOADEe8mz6FuZkNzV46H8RNvi77FojJqb3bz9RQapo,11279
29
- fastapi_factory_utilities/core/plugins/opentelemetry_plugin/__init__.py,sha256=4mq4a6U_nRxe3VxpHnC0FhRh0hpKO8l6QSUE7AazeBw,4689
37
+ fastapi_factory_utilities/core/plugins/odm_plugin/helpers.py,sha256=s9iEujDZbTmTb9FByJAVUzLkjQpsciQT9dytkeosKuE,463
38
+ fastapi_factory_utilities/core/plugins/odm_plugin/plugins.py,sha256=0jsLtw4NxZB6bDcBLBvWHqB-RELoewsSXTJdAOGunSY,6443
39
+ fastapi_factory_utilities/core/plugins/odm_plugin/repositories.py,sha256=GJ3ovlxzTpiJ2_XlgARtwn6j0SbQxxAray_r8QWvGok,11313
40
+ fastapi_factory_utilities/core/plugins/opentelemetry_plugin/__init__.py,sha256=xXHn5dUxhgdDDQMpTHf3voolzS0E3zE2RFbtFHJzb38,641
30
41
  fastapi_factory_utilities/core/plugins/opentelemetry_plugin/builder.py,sha256=9npQImifYAbEg0lFG7KwZ8V78SNrPoaINgd8vKitdMw,12509
31
42
  fastapi_factory_utilities/core/plugins/opentelemetry_plugin/configs.py,sha256=pMG9leMB7rtdkdGFLIxXflV7bf9epGrrYPt2N97KZcM,3750
32
43
  fastapi_factory_utilities/core/plugins/opentelemetry_plugin/exceptions.py,sha256=CpsHayfQpP0zghN8y5PP6TBy-cXhHoNxBR--I86gAdE,327
33
44
  fastapi_factory_utilities/core/plugins/opentelemetry_plugin/helpers.py,sha256=qpTIzX67orJz7vy6SBIwRs24omMBoToJkhpurZRjPuk,1533
34
- fastapi_factory_utilities/core/protocols.py,sha256=TzZKr_KfmTphk2LL-TD2XzxNlLbihbGM2DxWMhc5lEQ,2428
35
- fastapi_factory_utilities/core/security/jwt.py,sha256=LuNVmTlONrmoKl7ghNv5JHV4qzMNOwuxJQlWgGSvBoo,5631
45
+ fastapi_factory_utilities/core/plugins/opentelemetry_plugin/instruments/__init__.py,sha256=lMtdd1DSDrFcXggf0qMpB1RJC7aBqWMpOBXxC8-bqPY,3307
46
+ fastapi_factory_utilities/core/plugins/opentelemetry_plugin/plugins.py,sha256=v9W4bqEljcRgeSL8pf-4yZ7SGXOFmxVoljthvcLdy6Q,5356
47
+ fastapi_factory_utilities/core/plugins/taskiq_plugins/__init__.py,sha256=6rjQJXYEsOOSP8Fhlc1oJJVnHBOAxkapUKTpbB2X-K0,776
48
+ fastapi_factory_utilities/core/plugins/taskiq_plugins/configs.py,sha256=O2rgFFWJNBUZ7ozfhM0Lj5Te-58qBNrQtw_N0mosAu4,304
49
+ fastapi_factory_utilities/core/plugins/taskiq_plugins/depends.py,sha256=XBxC1uUdMhYtqZDqmUEKI80y5L7mDoXXjN8dZjEvVAo,1602
50
+ fastapi_factory_utilities/core/plugins/taskiq_plugins/exceptions.py,sha256=1Xq_DqDFiQm2YU-2pGxziy-EeMhHiUsUwV0XdY_rQls,456
51
+ fastapi_factory_utilities/core/plugins/taskiq_plugins/plugin.py,sha256=gUlU2s7aLB2lkAAPdLqVc-BY16PessSYTGMGgNcKCSA,1602
52
+ fastapi_factory_utilities/core/plugins/taskiq_plugins/schedulers.py,sha256=82Yh7Y_MUxiWjrHPnsW_Ax-CWREAT6eC_bVl-HW5a3E,7208
53
+ fastapi_factory_utilities/core/protocols.py,sha256=w5FQqMAZ_OulG5hQWkoOapNSnxsjBPq4EjvWNXXdI_c,859
54
+ fastapi_factory_utilities/core/security/jwt.py,sha256=BrP9EmtuOxjafHKluYzRtGdZYankv72iQgG49t9TgJw,5640
36
55
  fastapi_factory_utilities/core/security/kratos.py,sha256=yP9-TkELeXRPRYE9aQRlOPlwvaUJ7VQpyAea8ucWUfg,3364
37
56
  fastapi_factory_utilities/core/services/hydra/__init__.py,sha256=AKBYNc3zW5OsCLLeFSXqmDbWbQefHUJxstLpsXLQEUQ,369
38
57
  fastapi_factory_utilities/core/services/hydra/exceptions.py,sha256=ePMrfZturU2IVcxOebR0CbVKKqprce_fK-4UXbPPgNI,450
@@ -43,7 +62,7 @@ fastapi_factory_utilities/core/services/kratos/enums.py,sha256=ULJppowlZbOjdnUIX
43
62
  fastapi_factory_utilities/core/services/kratos/exceptions.py,sha256=xAX01-lQvPpADgcwhB5YWSy1UqAxG38s2rlU9AJBJd8,472
44
63
  fastapi_factory_utilities/core/services/kratos/objects.py,sha256=a0npt4Q6d9UbF0w3e6EvyKLwMWO2l639_dFjruA8_2c,980
45
64
  fastapi_factory_utilities/core/services/kratos/services.py,sha256=RFKrME6M6omWiHORMBCSyvIG0BsimQaCfnmtsOdFfsg,3158
46
- fastapi_factory_utilities/core/services/status/__init__.py,sha256=N5H0cCN9ZFu_0YZar4RLdCDEjKMICrIhNtfKgB0LI78,370
65
+ fastapi_factory_utilities/core/services/status/__init__.py,sha256=kkR2Xx-kbHb_QXkkBSUNIK5y_eNM4YCElFftBAooIY0,370
47
66
  fastapi_factory_utilities/core/services/status/enums.py,sha256=IUxWAd0Ecknri4BqzaqoDRRhT_8LdcgtQcNqgNVDXGE,599
48
67
  fastapi_factory_utilities/core/services/status/exceptions.py,sha256=_fQFGqHKnG54Hs-ZtC4gs0xwzSH246_WwQOonraoGKw,856
49
68
  fastapi_factory_utilities/core/services/status/health_calculator_strategies.py,sha256=p2KKJo-dq1j9iWHT0mvlBKtldH9m8l31aytLkUsb9nQ,1634
@@ -53,30 +72,30 @@ fastapi_factory_utilities/core/services/status/types.py,sha256=GJOGRra6NtpUS4q1c
53
72
  fastapi_factory_utilities/core/utils/configs.py,sha256=qM0pCrsK8ZyfCoyova_VrhR4eUX3LSPCbWunGMWcSVg,2581
54
73
  fastapi_factory_utilities/core/utils/importlib.py,sha256=DYcPo7K0s95WV5xxtucpufWsTj8Pxv25sWunDmmNUYI,797
55
74
  fastapi_factory_utilities/core/utils/log.py,sha256=6V9CL3bQio4e47YxcSXM2JQRGhVxuBfmcEbcF4RtCfQ,6393
56
- fastapi_factory_utilities/core/utils/status.py,sha256=1zxur98Wfum3JzpuzoAPoRIwQmXhFsTS2oxgbn5uFfg,1933
75
+ fastapi_factory_utilities/core/utils/status.py,sha256=ADdi4NzkJy0qNVC86tKV09wdpuPhuCKSrvYn9tzNVn8,1934
57
76
  fastapi_factory_utilities/core/utils/uvicorn.py,sha256=XThylG-nOPVL00w6MIWGODnweoM7VxmpSFcyoPcmqns,2609
58
- fastapi_factory_utilities/core/utils/yaml_reader.py,sha256=KNlwHvpraAp04JjeXSSk72BLuILH3lhEKrmRaUUgo2k,6103
77
+ fastapi_factory_utilities/core/utils/yaml_reader.py,sha256=2XenSHqymZsgff70upPZtyx0-BsiUdTENKmrxaOBLeE,6100
59
78
  fastapi_factory_utilities/example/__init__.py,sha256=LEKnPTBcgDyfHeOjlVxjK5lFdFqS-7-mHDuVuM2Jh_Y,206
60
79
  fastapi_factory_utilities/example/__main__.py,sha256=Iwp_6rK7Lcv2F-XAKn6xjxQHOWjx2OjgwKAr91tfUfk,135
61
80
  fastapi_factory_utilities/example/api/__init__.py,sha256=qI82eeSwVjR6jSkX1pxm8ALv9WPQ_iHurFY4G2K7VzE,554
62
81
  fastapi_factory_utilities/example/api/books/__init__.py,sha256=zXARBnjywJwg1XsLbcixYWcHH4uC9mF-kbbX4P8cVgA,160
63
82
  fastapi_factory_utilities/example/api/books/responses.py,sha256=21WeD6bdg0MCD_0vRHwmsL4W79iDcG9NnDLemXysc84,540
64
83
  fastapi_factory_utilities/example/api/books/routes.py,sha256=bwg8Bhvoj9vx2SdwunzFS-Z3cHECtjl_yGdo8MfiGEM,1529
65
- fastapi_factory_utilities/example/app.py,sha256=mcXQOg0A74mc8xFT0XuRHne3YjXXI7dTMV48G_Ypng8,1555
84
+ fastapi_factory_utilities/example/app.py,sha256=MInt71wnDEC9yqVJeT3hChj7DRmg7sI3Ta0KkfubdyU,2076
66
85
  fastapi_factory_utilities/example/application.yaml,sha256=5xRyFSuMxmgZ5Mikai94UqKYJ7PxJp8omlXobTjv14M,485
67
- fastapi_factory_utilities/example/entities/books/__init__.py,sha256=q2UTwLyCs3te38n7RgwT0go3Hp0bE9-NvoX7P-DR-3o,185
86
+ fastapi_factory_utilities/example/entities/books/__init__.py,sha256=cpTMhLpenb359lOT9HHUv6DzKX8fKl4WCzcsB3ddk6Q,185
68
87
  fastapi_factory_utilities/example/entities/books/entities.py,sha256=rLE01lE7U6WizrD5ZHMRwkynd8_dWF6DltBFH61f-Do,405
69
88
  fastapi_factory_utilities/example/entities/books/enums.py,sha256=lXYUvhIkT1pi0teflMpnqeafeiBZMokyWxoFLgzV6a8,330
70
89
  fastapi_factory_utilities/example/entities/books/types.py,sha256=7LYGPu-CcI3noIORJyIZlVF-CBugWPXEqgDzWrO3XmQ,1558
71
90
  fastapi_factory_utilities/example/models/__init__.py,sha256=RJmp3R9bhbQv7n0WOlsHP65LqbEs_DjF9hzYKwYTRGo,22
72
- fastapi_factory_utilities/example/models/books/__init__.py,sha256=1GJFCYMGZugQRxlFl-q7fPBFvNsl2ykeW8lV7rpURHU,181
91
+ fastapi_factory_utilities/example/models/books/__init__.py,sha256=IPS3rLLnZncV-VAxgsipxUD7l4r04ewo_Hx2Naj2lT0,181
73
92
  fastapi_factory_utilities/example/models/books/document.py,sha256=lYJfMGr5GqEEsn7L--PFs75hC2q-jQx77wl7EhTrp5U,568
74
93
  fastapi_factory_utilities/example/models/books/repository.py,sha256=7K63uAsSEGZ2EXqufU4Tc8KpymgXK8JX8WjAE2Sw8ok,387
75
94
  fastapi_factory_utilities/example/services/books/__init__.py,sha256=Z06yNRoA7Zg3TGN-Q9rrvJg6Bbx-qJw661MVwukV6vQ,148
76
95
  fastapi_factory_utilities/example/services/books/services.py,sha256=-x7d4hotUWLzWo5uImMjFmtNcSTHwWv2bfttIbYYKbA,5380
77
96
  fastapi_factory_utilities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
- fastapi_factory_utilities-0.4.0.dist-info/LICENSE,sha256=iO1nLzMMst6vEiqgSUrfrbetM7b0bvdzXhbed5tqG8o,1074
79
- fastapi_factory_utilities-0.4.0.dist-info/METADATA,sha256=BKswnNy_dt9__jBRcefkF5Ol2AxoI1TMDUs_UQ8_L-M,3478
80
- fastapi_factory_utilities-0.4.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
81
- fastapi_factory_utilities-0.4.0.dist-info/entry_points.txt,sha256=IK0VcBexXo4uXQmTrbfhhnnfq4GmXPRn0GBB8hzlsq4,101
82
- fastapi_factory_utilities-0.4.0.dist-info/RECORD,,
97
+ fastapi_factory_utilities-0.7.1.dist-info/METADATA,sha256=Qa2ulopX-2Fb4an_JoqjlEMZRwyfeMPKAv0GfCvHv7g,3741
98
+ fastapi_factory_utilities-0.7.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
99
+ fastapi_factory_utilities-0.7.1.dist-info/entry_points.txt,sha256=IK0VcBexXo4uXQmTrbfhhnnfq4GmXPRn0GBB8hzlsq4,101
100
+ fastapi_factory_utilities-0.7.1.dist-info/licenses/LICENSE,sha256=iO1nLzMMst6vEiqgSUrfrbetM7b0bvdzXhbed5tqG8o,1074
101
+ fastapi_factory_utilities-0.7.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any