Skip to content

Commit 45a1420

Browse files
authored
Merge branch 'main' into feat-ping-all-brokers
2 parents 415a3ac + 5e37604 commit 45a1420

File tree

8 files changed

+106
-18
lines changed

8 files changed

+106
-18
lines changed

faststream/asyncapi/generate.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ def get_app_schema(app: Union["FastStream", "StreamRouter[Any]"]) -> Schema:
5757
payloads,
5858
messages,
5959
)
60-
6160
schema = Schema(
6261
info=Info(
6362
title=app.title,
@@ -146,9 +145,13 @@ def _resolve_msg_payloads(
146145
payloads: Dict[str, Any],
147146
messages: Dict[str, Any],
148147
) -> Reference:
149-
one_of_list: List[Reference] = []
148+
"""Replace message payload by reference and normalize payloads.
150149
150+
Payloads and messages are editable dicts to store schemas for reference in AsyncAPI.
151+
"""
152+
one_of_list: List[Reference] = []
151153
m.payload = _move_pydantic_refs(m.payload, DEF_KEY)
154+
152155
if DEF_KEY in m.payload:
153156
payloads.update(m.payload.pop(DEF_KEY))
154157

@@ -186,6 +189,7 @@ def _move_pydantic_refs(
186189
original: Any,
187190
key: str,
188191
) -> Any:
192+
"""Remove pydantic references and replacem them by real schemas."""
189193
if not isinstance(original, Dict):
190194
return original
191195

faststream/broker/subscriber/usecase.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,9 @@ def get_log_context(
407407
@property
408408
def call_name(self) -> str:
409409
"""Returns the name of the handler call."""
410-
# TODO: default call_name
410+
if not self.calls:
411+
return "Subscriber"
412+
411413
return to_camelcase(self.calls[0].call_name)
412414

413415
def get_description(self) -> Optional[str]:
@@ -433,4 +435,14 @@ def get_payloads(self) -> List[Tuple["AnyDict", str]]:
433435

434436
payloads.append((body, to_camelcase(h.call_name)))
435437

438+
if not self.calls:
439+
payloads.append(
440+
(
441+
{
442+
"title": f"{self.title_ or self.call_name}:Message:Payload",
443+
},
444+
to_camelcase(self.call_name),
445+
)
446+
)
447+
436448
return payloads

faststream/confluent/security.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ def parse_security(security: Optional[BaseSecurity]) -> "AnyDict":
2121

2222
if security is None:
2323
return {}
24-
elif type(security) == BaseSecurity:
25-
return _parse_base_security(security)
26-
elif type(security) == SASLPlaintext:
24+
elif isinstance(security, SASLPlaintext):
2725
return _parse_sasl_plaintext(security)
28-
elif type(security) == SASLScram256:
26+
elif isinstance(security, SASLScram256):
2927
return _parse_sasl_scram256(security)
30-
elif type(security) == SASLScram512:
28+
elif isinstance(security, SASLScram512):
3129
return _parse_sasl_scram512(security)
30+
elif isinstance(security, BaseSecurity):
31+
return _parse_base_security(security)
3232
else:
3333
raise NotImplementedError(f"KafkaBroker does not support `{type(security)}`.")
3434

faststream/confluent/subscriber/asyncapi.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ def get_schema(self) -> Dict[str, Channel]:
3434
channels = {}
3535

3636
payloads = self.get_payloads()
37-
3837
for t in self.topics:
3938
handler_name = self.title_ or f"{t}:{self.call_name}"
4039

faststream/kafka/security.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
def parse_security(security: Optional[BaseSecurity]) -> "AnyDict":
1515
if security is None:
1616
return {}
17-
elif type(security) == BaseSecurity:
18-
return _parse_base_security(security)
19-
elif type(security) == SASLPlaintext:
17+
elif isinstance(security, SASLPlaintext):
2018
return _parse_sasl_plaintext(security)
21-
elif type(security) == SASLScram256:
19+
elif isinstance(security, SASLScram256):
2220
return _parse_sasl_scram256(security)
23-
elif type(security) == SASLScram512:
21+
elif isinstance(security, SASLScram512):
2422
return _parse_sasl_scram512(security)
23+
elif isinstance(security, BaseSecurity):
24+
return _parse_base_security(security)
2525
else:
2626
raise NotImplementedError(f"KafkaBroker does not support `{type(security)}`.")
2727

faststream/nats/subscriber/usecase.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ async def _create_subscription( # type: ignore[override]
700700
"""Create NATS subscription and start consume task."""
701701
self.subscription = await connection.pull_subscribe(
702702
subject=self.clear_subject,
703+
config=self.config,
703704
**self.extra_options,
704705
)
705706
self.add_task(self._consume_pull(cb=self.consume))
@@ -778,6 +779,7 @@ async def _create_subscription( # type: ignore[override]
778779

779780
self.subscription = await connection.pull_subscribe(
780781
subject=self.clear_subject,
782+
config=self.config,
781783
**self.extra_options,
782784
)
783785
self.add_task(self._consume_pull(cb=self._put_msg))
@@ -841,6 +843,7 @@ async def _create_subscription( # type: ignore[override]
841843
"""Create NATS subscription and start consume task."""
842844
self.subscription = await connection.pull_subscribe(
843845
subject=self.clear_subject,
846+
config=self.config,
844847
**self.extra_options,
845848
)
846849
self.add_task(self._consume_pull())

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ otel = ["opentelemetry-sdk>=1.24.0,<2.0.0"]
7979
optionals = ["faststream[rabbit,kafka,confluent,nats,redis,otel]"]
8080

8181
devdocs = [
82-
"mkdocs-material==9.5.27",
82+
"mkdocs-material==9.5.29",
8383
"mkdocs-static-i18n==1.2.3",
8484
"mdx-include==1.4.2",
8585
"mkdocstrings[python]==0.25.1",
@@ -111,14 +111,14 @@ types = [
111111

112112
lint = [
113113
"faststream[types]",
114-
"ruff==0.5.1",
114+
"ruff==0.5.2",
115115
"bandit==1.7.9",
116116
"semgrep==1.79.0",
117117
"codespell==2.3.0",
118118
]
119119

120120
test-core = [
121-
"coverage[toml]==7.5.4",
121+
"coverage[toml]==7.6.0",
122122
"pytest==8.2.2",
123123
"pytest-asyncio==0.23.7",
124124
"dirty-equals==0.7.1.post0",
@@ -127,7 +127,7 @@ test-core = [
127127

128128
testing = [
129129
"faststream[test-core]",
130-
"fastapi==0.111.0",
130+
"fastapi==0.111.1",
131131
"pydantic-settings>=2.0.0,<3.0.0",
132132
"httpx==0.27.0",
133133
"PyYAML==6.0.1",

tests/asyncapi/base/naming.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,76 @@ async def handle_user_created(msg: str): ...
9090
"custom:Message:Payload"
9191
]
9292

93+
def test_subscriber_naming_default(self):
94+
broker = self.broker_class()
95+
96+
broker.subscriber("test")
97+
98+
schema = get_app_schema(FastStream(broker)).to_jsonable()
99+
100+
assert list(schema["channels"].keys()) == [
101+
IsStr(regex=r"test[\w:]*:Subscriber")
102+
]
103+
104+
assert list(schema["components"]["messages"].keys()) == [
105+
IsStr(regex=r"test[\w:]*:Subscriber:Message")
106+
]
107+
108+
for key, v in schema["components"]["schemas"].items():
109+
assert key == "Subscriber:Message:Payload"
110+
assert v == {"title": key}
111+
112+
def test_subscriber_naming_default_with_title(self):
113+
broker = self.broker_class()
114+
115+
broker.subscriber("test", title="custom")
116+
117+
schema = get_app_schema(FastStream(broker)).to_jsonable()
118+
119+
assert list(schema["channels"].keys()) == ["custom"]
120+
121+
assert list(schema["components"]["messages"].keys()) == ["custom:Message"]
122+
123+
assert list(schema["components"]["schemas"].keys()) == [
124+
"custom:Message:Payload"
125+
]
126+
127+
assert schema["components"]["schemas"]["custom:Message:Payload"] == {
128+
"title": "custom:Message:Payload"
129+
}
130+
131+
def test_multi_subscribers_naming_default(self):
132+
broker = self.broker_class()
133+
134+
@broker.subscriber("test")
135+
async def handle_user_created(msg: str): ...
136+
137+
broker.subscriber("test2")
138+
broker.subscriber("test3")
139+
140+
schema = get_app_schema(FastStream(broker)).to_jsonable()
141+
142+
assert list(schema["channels"].keys()) == [
143+
IsStr(regex=r"test[\w:]*:HandleUserCreated"),
144+
IsStr(regex=r"test2[\w:]*:Subscriber"),
145+
IsStr(regex=r"test3[\w:]*:Subscriber"),
146+
]
147+
148+
assert list(schema["components"]["messages"].keys()) == [
149+
IsStr(regex=r"test[\w:]*:HandleUserCreated:Message"),
150+
IsStr(regex=r"test2[\w:]*:Subscriber:Message"),
151+
IsStr(regex=r"test3[\w:]*:Subscriber:Message"),
152+
]
153+
154+
assert list(schema["components"]["schemas"].keys()) == [
155+
"HandleUserCreated:Message:Payload",
156+
"Subscriber:Message:Payload",
157+
]
158+
159+
assert schema["components"]["schemas"]["Subscriber:Message:Payload"] == {
160+
"title": "Subscriber:Message:Payload"
161+
}
162+
93163

94164
class FilterNaming(BaseNaming):
95165
def test_subscriber_filter_base(self):

0 commit comments

Comments
 (0)