faststream_fastapi 1.0.0__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.
@@ -0,0 +1,180 @@
1
+ import inspect
2
+ from collections.abc import Awaitable, Callable, Iterable
3
+ from contextlib import AsyncExitStack
4
+ from functools import wraps
5
+ from itertools import dropwhile
6
+ from typing import Any, ParamSpec, TypeVar
7
+
8
+ from fast_depends.dependencies import Dependant
9
+ from fastapi.dependencies.models import Dependant as FastAPIDependant
10
+ from fastapi.params import Depends
11
+ from fastapi.routing import run_endpoint_function, serialize_response
12
+ from faststream.exceptions import SetupError
13
+ from faststream.message import StreamMessage as NativeMessage
14
+ from faststream.response import Response, ensure_response
15
+
16
+ from faststream_fastapi._internal.config import Config
17
+ from faststream_fastapi._internal.fastapi_compat import (
18
+ FASTAPI_V106,
19
+ FASTAPI_V121,
20
+ raise_fastapi_validation_error,
21
+ solve_faststream_dependency,
22
+ )
23
+ from faststream_fastapi._internal.fs_re_exports.context import ContextRepo
24
+ from faststream_fastapi._internal.get_dependant import (
25
+ get_fastapi_native_dependant,
26
+ has_forbidden_types,
27
+ is_faststream_decorated,
28
+ mark_faststream_decorated,
29
+ )
30
+ from faststream_fastapi._internal.replace_context import replace_context
31
+ from faststream_fastapi.stream_message import StreamMessage
32
+
33
+ P_HandlerParams = ParamSpec("P_HandlerParams")
34
+ T_HandlerReturn = TypeVar("T_HandlerReturn")
35
+
36
+
37
+ def wrap_callable_to_fastapi_compatible(
38
+ user_callable: Callable[P_HandlerParams, T_HandlerReturn],
39
+ *,
40
+ config: Config,
41
+ context: ContextRepo,
42
+ dependencies: Iterable[Depends],
43
+ ) -> Callable[[NativeMessage[Any]], Awaitable[Any]]:
44
+ user_callable = replace_context(user_callable)
45
+
46
+ if has_forbidden_types(user_callable, (Dependant,)):
47
+ msg = (
48
+ f"Incorrect `faststream.Depends` usage at `{user_callable.__name__}`. "
49
+ "For FastAPI integration use `fastapi.Depends` instead."
50
+ )
51
+ raise SetupError(msg)
52
+
53
+ if is_faststream_decorated(user_callable):
54
+ return user_callable # type: ignore[return-value]
55
+
56
+ parsed_callable = build_faststream_to_fastapi_parser(
57
+ dependent=get_fastapi_native_dependant(user_callable, dependencies),
58
+ config=config,
59
+ context=context,
60
+ )
61
+
62
+ mark_faststream_decorated(parsed_callable)
63
+ return wraps(user_callable)(parsed_callable)
64
+
65
+
66
+ def build_faststream_to_fastapi_parser(
67
+ *,
68
+ dependent: FastAPIDependant,
69
+ config: Config,
70
+ context: ContextRepo,
71
+ ) -> Callable[[NativeMessage[Any]], Awaitable[Any]]:
72
+ if dependent.call is None: # pragma: no cover
73
+ raise ValueError("dependent.call is None") # noqa: TRY003
74
+
75
+ consume = make_fastapi_execution(
76
+ dependent=dependent,
77
+ config=config,
78
+ )
79
+
80
+ dependencies_names = tuple(i.name for i in dependent.dependencies)
81
+
82
+ first_arg = next(
83
+ dropwhile(
84
+ lambda i: i in dependencies_names,
85
+ inspect.signature(dependent.call).parameters,
86
+ ),
87
+ None,
88
+ )
89
+
90
+ async def parsed_consumer(message: NativeMessage[Any]) -> Any:
91
+ body = await message.decode()
92
+
93
+ fastapi_body: dict[str, Any] | list[Any]
94
+ stream_message: StreamMessage
95
+ if first_arg is not None:
96
+ if isinstance(body, dict):
97
+ path = fastapi_body = body or {}
98
+ elif isinstance(body, list):
99
+ fastapi_body, path = body, {}
100
+ else:
101
+ path = fastapi_body = {first_arg: body}
102
+
103
+ stream_message = StreamMessage(
104
+ body=fastapi_body,
105
+ headers={"context__": context, **message.headers},
106
+ path={**path, **message.path},
107
+ )
108
+
109
+ else:
110
+ stream_message = StreamMessage(
111
+ body={},
112
+ headers={"context__": context},
113
+ path={},
114
+ )
115
+ return await consume(stream_message, message)
116
+
117
+ return parsed_consumer
118
+
119
+
120
+ def make_fastapi_execution(
121
+ *,
122
+ dependent: FastAPIDependant,
123
+ config: Config,
124
+ ) -> Callable[
125
+ [StreamMessage, NativeMessage[Any]],
126
+ Awaitable[Response],
127
+ ]:
128
+ is_coroutine = inspect.iscoroutinefunction(dependent.call)
129
+
130
+ async def app(
131
+ request: StreamMessage,
132
+ raw_message: NativeMessage[Any], # to support BackgroundTasks by middleware
133
+ ) -> Response:
134
+ async with AsyncExitStack() as stack:
135
+ kwargs = {}
136
+ if FASTAPI_V121:
137
+ request.scope["fastapi_inner_astack"] = stack
138
+ function_stack = AsyncExitStack()
139
+ await stack.enter_async_context(function_stack)
140
+ request.scope["fastapi_function_astack"] = function_stack
141
+
142
+ if FASTAPI_V106:
143
+ kwargs = {"async_exit_stack": stack}
144
+
145
+ else: # pragma: no cover
146
+ request.scope["fastapi_astack"] = stack
147
+
148
+ request.scope["app"] = config.application
149
+ request.scope["state"] = config.asgi_state
150
+
151
+ solved_result = await solve_faststream_dependency(
152
+ request=request,
153
+ dependant=dependent,
154
+ dependency_overrides_provider=config.dependency_overrides_provider,
155
+ **kwargs,
156
+ )
157
+
158
+ raw_message.background = solved_result.background_tasks # type: ignore[attr-defined]
159
+
160
+ if solved_result.errors:
161
+ raise_fastapi_validation_error(solved_result.errors, request._body) # type: ignore[arg-type]
162
+
163
+ function_result = await run_endpoint_function(
164
+ dependant=dependent,
165
+ values=solved_result.values,
166
+ is_coroutine=is_coroutine,
167
+ )
168
+
169
+ response = ensure_response(function_result)
170
+
171
+ response.body = await serialize_response(
172
+ response_content=response.body,
173
+ is_coroutine=is_coroutine,
174
+ )
175
+
176
+ return response
177
+
178
+ raise AssertionError("unreachable")
179
+
180
+ return app
@@ -0,0 +1,71 @@
1
+ from collections.abc import Sequence
2
+ from typing import Any
3
+
4
+ from faststream.specification.asyncapi.site import (
5
+ ASYNCAPI_CSS_DEFAULT_URL,
6
+ ASYNCAPI_JS_DEFAULT_URL,
7
+ ASYNCAPI_TRY_IT_PLUGIN_URL,
8
+ )
9
+ from faststream.specification.schema import Tag, TagDict
10
+
11
+
12
+ class _Empty: ...
13
+
14
+
15
+ _EMPTY = _Empty()
16
+
17
+
18
+ class AsyncAPIConfig:
19
+ def __init__(
20
+ self,
21
+ path: str,
22
+ *,
23
+ description: str | None = None,
24
+ tags: Sequence[Tag | TagDict | dict[str, Any]] | None = None,
25
+ unique_id: str | None = None,
26
+ include_in_schema: bool = False,
27
+ asyncapi_json_path: str | None | _Empty = _EMPTY,
28
+ asyncapi_yaml_path: str | None | _Empty = _EMPTY,
29
+ try_it_out_path: str | None | _Empty = _EMPTY,
30
+ sidebar: bool = True,
31
+ info: bool = True,
32
+ servers: bool = True,
33
+ operations: bool = True,
34
+ messages: bool = True,
35
+ schemas: bool = True,
36
+ errors: bool = True,
37
+ expand_message_examples: bool = True,
38
+ asyncapi_js_url: str = ASYNCAPI_JS_DEFAULT_URL,
39
+ asyncapi_css_url: str = ASYNCAPI_CSS_DEFAULT_URL,
40
+ try_it_out_plugin_url: str = ASYNCAPI_TRY_IT_PLUGIN_URL,
41
+ ) -> None:
42
+ self.path = path
43
+
44
+ if isinstance(asyncapi_json_path, _Empty):
45
+ asyncapi_json_path = path.rstrip("/") + ".json"
46
+ self.asyncapi_json_path = asyncapi_json_path
47
+
48
+ if isinstance(asyncapi_yaml_path, _Empty):
49
+ asyncapi_yaml_path = path.rstrip("/") + ".yaml"
50
+ self.asyncapi_yaml_path = asyncapi_yaml_path
51
+
52
+ if isinstance(try_it_out_path, _Empty):
53
+ try_it_out_path = path.rstrip("/") + "/try"
54
+ self.try_it_out_path = try_it_out_path
55
+
56
+ self.description = description
57
+ self.tags = tags
58
+ self.unique_id = unique_id
59
+ self.include_in_schema = include_in_schema
60
+
61
+ self.sidebar = sidebar
62
+ self.info = info
63
+ self.servers = servers
64
+ self.operations = operations
65
+ self.messages = messages
66
+ self.schemas = schemas
67
+ self.errors = errors
68
+ self.expand_message_examples = expand_message_examples
69
+ self.asyncapi_js_url = asyncapi_js_url
70
+ self.asyncapi_css_url = asyncapi_css_url
71
+ self.try_it_out_plugin_url = try_it_out_plugin_url
@@ -0,0 +1,31 @@
1
+ from collections.abc import Callable
2
+ from typing import Annotated, Any
3
+
4
+ from fastapi import params
5
+
6
+ from faststream_fastapi._internal.fs_re_exports.constants import EMPTY
7
+ from faststream_fastapi._internal.fs_re_exports.context import (
8
+ resolve_context_by_name,
9
+ )
10
+
11
+
12
+ def Context( # noqa: N802
13
+ name: str = "",
14
+ *,
15
+ default: Any = EMPTY,
16
+ initial: Callable[..., Any] | None = None,
17
+ ) -> Any:
18
+ def solve_context(
19
+ context: Annotated[
20
+ Any,
21
+ params.Header(alias="context__", include_in_schema=False),
22
+ ],
23
+ ) -> Any:
24
+ return resolve_context_by_name(
25
+ name=name,
26
+ default=default,
27
+ initial=initial,
28
+ context=context,
29
+ )
30
+
31
+ return params.Depends(solve_context, use_cache=True)
@@ -0,0 +1,165 @@
1
+ import traceback
2
+ from collections.abc import AsyncIterator, Awaitable, Callable, Iterable
3
+ from contextlib import asynccontextmanager
4
+ from typing import Any
5
+
6
+ from fastapi import FastAPI
7
+ from fastapi.params import Depends
8
+ from faststream.message import StreamMessage
9
+ from faststream.specification.base import SpecificationFactory
10
+ from starlette.types import Receive, Scope, Send
11
+
12
+ from faststream_fastapi._internal.asyncapi_router import AsyncAPIRouter
13
+ from faststream_fastapi._internal.background_middleware import _BackgroundMiddleware
14
+ from faststream_fastapi._internal.config import Config
15
+ from faststream_fastapi._internal.fs_re_exports.application import StartAbleApplication
16
+ from faststream_fastapi._internal.fs_re_exports.broker import BrokerUsecase
17
+ from faststream_fastapi._internal.fs_re_exports.context import ContextRepo
18
+ from faststream_fastapi._internal.fs_re_exports.di import FastDependsConfig
19
+ from faststream_fastapi._internal.get_dependant import get_fastapi_dependant
20
+ from faststream_fastapi._internal.wrap_callable_to_fastapi_compatible import (
21
+ wrap_callable_to_fastapi_compatible,
22
+ )
23
+ from faststream_fastapi.asyncapi_config import AsyncAPIConfig
24
+
25
+
26
+ def _subscriber_compatibility_wrapper(
27
+ config: Config,
28
+ context: ContextRepo,
29
+ dependencies: Iterable[Depends],
30
+ ) -> Callable[[Callable[..., Any]], Callable[["StreamMessage[Any]"], Awaitable[Any]]]:
31
+ def subscriber_compatibility_wrapper(
32
+ endpoint: Callable[..., Any],
33
+ ) -> Callable[["StreamMessage[Any]"], Awaitable[Any]]:
34
+ return wrap_callable_to_fastapi_compatible(
35
+ user_callable=endpoint,
36
+ config=config,
37
+ context=context,
38
+ dependencies=dependencies,
39
+ )
40
+
41
+ return subscriber_compatibility_wrapper
42
+
43
+
44
+ class FastStreamAPI:
45
+ def __init__(
46
+ self,
47
+ *brokers: BrokerUsecase[Any, Any],
48
+ application: FastAPI,
49
+ context: ContextRepo | None = None,
50
+ # AsyncAPI
51
+ specification: SpecificationFactory | None = None,
52
+ asyncapi_path: str | AsyncAPIConfig | None = None,
53
+ ) -> None:
54
+ self._application = application
55
+
56
+ self._brokers = brokers
57
+
58
+ self._startable_application = StartAbleApplication(
59
+ *brokers,
60
+ specification=specification,
61
+ config=FastDependsConfig(
62
+ get_dependent=get_fastapi_dependant,
63
+ context=context or ContextRepo(),
64
+ ),
65
+ )
66
+
67
+ self._config = Config(
68
+ application=application,
69
+ dependency_overrides_provider=self._application,
70
+ )
71
+
72
+ if asyncapi_path is not None:
73
+ if isinstance(asyncapi_path, str):
74
+ asyncapi_config = AsyncAPIConfig(asyncapi_path)
75
+ else:
76
+ asyncapi_config = asyncapi_path
77
+
78
+ else:
79
+ asyncapi_config = None
80
+
81
+ self._asyncapi_config = asyncapi_config
82
+
83
+ for broker in self._brokers:
84
+ broker.config.add_middleware(_BackgroundMiddleware)
85
+
86
+ for subscriber in broker.subscribers:
87
+ dependencies = (
88
+ *broker.config.broker_dependencies,
89
+ *subscriber._call_options.dependencies,
90
+ )
91
+ subscriber._call_decorators = (
92
+ _subscriber_compatibility_wrapper(
93
+ config=self._config,
94
+ context=self._startable_application.context,
95
+ dependencies=dependencies, # type: ignore[arg-type]
96
+ ),
97
+ *subscriber._call_decorators,
98
+ )
99
+
100
+ # For FastStream docs gen
101
+ @property
102
+ def schema(self) -> SpecificationFactory:
103
+ return self._startable_application.schema
104
+
105
+ @property
106
+ def context(self) -> ContextRepo:
107
+ return self._startable_application.context
108
+
109
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
110
+ if scope["type"] == "lifespan":
111
+ await self.lifespan(scope, receive, send)
112
+ return None
113
+
114
+ return await self._application(scope, receive, send)
115
+
116
+ async def lifespan(self, scope: Scope, receive: Receive, send: Send) -> None:
117
+ started = False
118
+ app: Any = scope.get("app")
119
+ await receive()
120
+ try:
121
+ async with (
122
+ self._lifespan_context(app),
123
+ self._application.router.lifespan_context(app) as maybe_state,
124
+ ):
125
+ if maybe_state is not None:
126
+ if "state" not in scope:
127
+ msg = 'The server does not support "state" in the lifespan scope.'
128
+ raise RuntimeError(msg) # noqa: TRY301
129
+
130
+ scope["state"].update(maybe_state)
131
+
132
+ await send({"type": "lifespan.startup.complete"})
133
+ started = True
134
+ await receive()
135
+ except BaseException:
136
+ exc_text = traceback.format_exc()
137
+ if started:
138
+ await send({"type": "lifespan.shutdown.failed", "message": exc_text})
139
+ else:
140
+ await send({"type": "lifespan.startup.failed", "message": exc_text})
141
+ raise
142
+ else:
143
+ await send({"type": "lifespan.shutdown.complete"})
144
+
145
+ @asynccontextmanager
146
+ async def _lifespan_context(self, application: Any) -> AsyncIterator[None]:
147
+ if self._asyncapi_config is not None:
148
+ asyncapi_router = AsyncAPIRouter(
149
+ brokers=self._brokers,
150
+ config=self._asyncapi_config,
151
+ schema=self._startable_application.schema,
152
+ )
153
+ self._application.include_router(asyncapi_router)
154
+
155
+ started_brokers: list[BrokerUsecase[Any, Any]] = []
156
+
157
+ try:
158
+ for broker in self._brokers:
159
+ await broker.start()
160
+ started_brokers.append(broker)
161
+
162
+ yield None
163
+ finally:
164
+ for started_broker in started_brokers:
165
+ await started_broker.stop()
@@ -0,0 +1,25 @@
1
+ from typing import Any
2
+
3
+ from fastapi import Request
4
+
5
+
6
+ class StreamMessage(Request):
7
+ scope: dict[str, Any]
8
+ _cookies: dict[str, Any]
9
+ _headers: dict[str, Any] # type: ignore[assignment]
10
+ _body: dict[str, Any] | list[Any] # type: ignore[assignment]
11
+ _query_params: dict[str, Any] # type: ignore[assignment]
12
+
13
+ def __init__(
14
+ self,
15
+ *,
16
+ body: dict[str, Any] | list[Any],
17
+ headers: dict[str, Any],
18
+ path: dict[str, Any],
19
+ ) -> None:
20
+ self._headers = headers
21
+ self._body = body
22
+ self._query_params = path
23
+
24
+ self.scope = {"path_params": self._query_params}
25
+ self._cookies = {}
@@ -0,0 +1,151 @@
1
+ Metadata-Version: 2.4
2
+ Name: faststream_fastapi
3
+ Version: 1.0.0
4
+ Summary: FastAPI integration for FastStream
5
+ Keywords: rabbitmq,kafka,nats,redis,mqtt,asyncapi,framework,message brokers,fastapi
6
+ Author: Ivan Kirpichnikov
7
+ Author-email: Ivan Kirpichnikov <mmssvvvv570@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: Implementation :: CPython
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: Software Development :: Libraries
24
+ Classifier: Topic :: Software Development
25
+ Classifier: Topic :: System :: Networking
26
+ Classifier: Topic :: System :: Distributed Computing
27
+ Classifier: Typing :: Typed
28
+ Classifier: Intended Audience :: Developers
29
+ Classifier: Intended Audience :: Information Technology
30
+ Classifier: Intended Audience :: System Administrators
31
+ Classifier: Environment :: Web Environment
32
+ Classifier: Framework :: AsyncIO
33
+ Classifier: Framework :: Pydantic
34
+ Classifier: Framework :: Pydantic :: 1
35
+ Classifier: Framework :: Pydantic :: 2
36
+ Requires-Dist: fastapi<1.0.0
37
+ Requires-Dist: faststream>=0.7.0
38
+ Requires-Python: >=3.10
39
+ Description-Content-Type: text/markdown
40
+
41
+ # FastAPI Plugin for FastStream
42
+
43
+ A plugin that allows you to use **Depends** and **FastAPI** other objects in the **FastStream**
44
+
45
+ # Features
46
+
47
+ ### Use FastAPI Dependency Injection
48
+ In **FastStream** handlers, it will be possible to use the familiar DI from **FastAPI**
49
+ ```py
50
+ from fastapi import Path, Body, Header, Depends
51
+
52
+ class BodyModel(BaseModel):
53
+ field: int
54
+
55
+ @broker.subscriber("subject.{num}")
56
+ async def subscriber_handler(
57
+ num: Annotated[int, Path()],
58
+ body: Annotated[BodyModel, Body()],
59
+ x_user_id: Annotated[int, Header()],
60
+ my_dep: Annotated[int, Depends(int)],
61
+ ) -> None:
62
+ ...
63
+ ```
64
+
65
+ ### Сan use FastAPI dependency overrides
66
+ ```py
67
+ fastapi = FastAPI()
68
+ fastapi.dependency_overrides[Dep] = lambda: "Dep"
69
+
70
+ @broker.subscriber("subject")
71
+ async def subscriber(dep: Annotated[str, De[]]) -> None:
72
+ assert dep == "Dep"
73
+ ```
74
+
75
+ ### Using the FastStream Context
76
+ ```py
77
+ from faststream import Context
78
+
79
+ @broker.subscriber("subject")
80
+ async def subscriber_handler(context_data: Annotated[int, Context("data")]) -> Response: ...
81
+ ```
82
+
83
+ ### Use FastAPI Request and Response
84
+ ```py
85
+ from fastapi import Request, Response
86
+ from fastapi.responses import JSONResponse
87
+
88
+ @broker.subscriber("subject")
89
+ async def subscriber_handler(request: Request) -> Response:
90
+ return JSONResponse({"data": 1})
91
+ ```
92
+
93
+ ### Minimalistic plugin connection to your application
94
+
95
+ All you need to do is wrap the **FastAPI** with the **FastStreamAPI** object from the **plugin**
96
+
97
+ ```py
98
+ application = FastStreamAPI(
99
+ NatsBroker(),
100
+ application=FastAPI(),
101
+ )
102
+ uvicorn.run(application)
103
+ ```
104
+
105
+ ### Managing a lifespan state
106
+ Now the **lifespan state** is also available in **FastStream handlers**
107
+
108
+ ```py
109
+ @asynccontextmanager
110
+ async def lifespan(app: FastAPI):
111
+ yield {"lifespan_data": "LIFESPAN DATA"}
112
+
113
+ @broker.subscriber("subject")
114
+ async def subscriber(request: Request) -> None:
115
+ assert request.state.lifespan_data == "LIFESPAN DATA"
116
+ ```
117
+
118
+ ### The ability to configure AsyncAPI
119
+
120
+ The ability to configure **AsyncAPI** using **SpecificationFactory** from **FastStream** and **AsyncAPIConfig** from the **plugin**
121
+
122
+ ```py
123
+ FastStreamAPI(
124
+ ...,
125
+ specification=AsyncAPI(
126
+ title="My app",
127
+ version="1.0.0",
128
+ description="...",
129
+ ...,
130
+ ),
131
+ asyncapi_path="/fs_docs",
132
+ # or
133
+ asyncapi_path=AsyncAPIRouter(
134
+ "/fs_docs",
135
+ description="...",
136
+ ...
137
+ ),
138
+ )
139
+ ```
140
+
141
+ ### Backgrounds tasks
142
+
143
+ You can use **BackgroundTasks** from **FastAPI** in **FastStream handlers**
144
+
145
+ ```py
146
+ @broker.subscriber("subject")
147
+ async def handler1(
148
+ tasks: BackgroundTasks,
149
+ ) -> None:
150
+ tasks.add_task(...)
151
+ ```
@@ -0,0 +1,27 @@
1
+ faststream_fastapi/__about__.py,sha256=oYISj9X_HBZogY0KMHgJ8v3EPboAd_XANLfWjFBtwMc,136
2
+ faststream_fastapi/__init__.py,sha256=Trs7HiP8zCim_vz7lyzN-7jDbLFNL2Vmes0lKmHsjGI,323
3
+ faststream_fastapi/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ faststream_fastapi/_internal/asyncapi_router.py,sha256=BIwHuAby1mhTQuoTRMWY2X2oa7_GGORB329Lj6ouXtc,4299
5
+ faststream_fastapi/_internal/background_middleware.py,sha256=3IvdDQ1ZBIzgIzeFamc2B4Z2YJMEAzdI7M96Ndvl7y0,717
6
+ faststream_fastapi/_internal/config.py,sha256=YmFNnpk6FpOTM_JGJgSbSE-MbT-pMh5SxBD-1yKEOvc,571
7
+ faststream_fastapi/_internal/fastapi_compat.py,sha256=0ChnQV7FbB2OsEWPwb74rDqwfeFMjXf8FN7qEkYjqnk,4362
8
+ faststream_fastapi/_internal/fs_re_exports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ faststream_fastapi/_internal/fs_re_exports/_compat.py,sha256=h7xdEqvop1FfFzKB4kZBsHtRSdNNXIRQNt7BYJQPHms,131
10
+ faststream_fastapi/_internal/fs_re_exports/application.py,sha256=ocziVIpGpB0IgOw_kimZAVdCF0OzBdTLCts3e5QlpOE,103
11
+ faststream_fastapi/_internal/fs_re_exports/broker.py,sha256=6mZ08_R_Z9e3qbDSYx_UdB8mQY1M_jJlU9ZrPT7EXW4,159
12
+ faststream_fastapi/_internal/fs_re_exports/constants.py,sha256=mJ8kiBNoF2VstW6sZ4LZY44Bwx1AUKJhb5mbd5DJMEE,71
13
+ faststream_fastapi/_internal/fs_re_exports/context.py,sha256=ep53p8_UYAgUVxFw7QAvqiZjbNfQ1QMLahriUraB_ZU,215
14
+ faststream_fastapi/_internal/fs_re_exports/di.py,sha256=x38rHqtwmrOduz7W31_Hke_7vXlKIGVtAQh-ej52w_0,88
15
+ faststream_fastapi/_internal/fs_re_exports/logger.py,sha256=SMxqu9YwIwLBa9hvzSFM-qYW_B48AsdhP1uL3LV1vEo,86
16
+ faststream_fastapi/_internal/get_dependant.py,sha256=ObQvRmywHTNM7c7zQM6VAtirCBtJhxH2f7-6DMxfcSk,5997
17
+ faststream_fastapi/_internal/logger.py,sha256=qaa8lXlQxtrp9hzDZHOijTBH0cKiV-2ZpUEbnjjdrUc,258
18
+ faststream_fastapi/_internal/replace_context.py,sha256=nCLVn8kTV9SuGS_whbyzXYi-pq96x8Vft5cll9vCpMo,3697
19
+ faststream_fastapi/_internal/wrap_callable_to_fastapi_compatible.py,sha256=LTotExCxEeqLEI7KAx82JSyzmz1PoXV8fpbvVqGPkfQ,5889
20
+ faststream_fastapi/asyncapi_config.py,sha256=2D5Jc8ByUztmMn12a2fcNWtvfHZPeIhffbW6bhUO9lM,2294
21
+ faststream_fastapi/context.py,sha256=bcE0DB8lQMPtCO3eTP3bNu1i_YL8uIOViwmk8IMiSGs,788
22
+ faststream_fastapi/faststream_api.py,sha256=RLXcwA5hqyp6Q90siNg_LGpXs3r_kYqnwtaqzH2Ptmw,6021
23
+ faststream_fastapi/stream_message.py,sha256=1k2vzUGL76wSJjbpPwL03LTBctRtD0syBlLqUuK5MpQ,665
24
+ faststream_fastapi-1.0.0.dist-info/licenses/LICENSE,sha256=ZDtF8IsAs002GXg_yHpuS_RLkXDOOjKFuGFSTYUiTY4,1074
25
+ faststream_fastapi-1.0.0.dist-info/WHEEL,sha256=8ZlpUMJ7mlDirmlHRhDirEx_nPnARrwDjeE92mlk68E,81
26
+ faststream_fastapi-1.0.0.dist-info/METADATA,sha256=UrIblBJ44uDZuCgiuNtzCkTFSTTlg6L6al3nNvmqNCM,4354
27
+ faststream_fastapi-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.11.21
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ivan Kirpichnikov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.