Skip to content

KafkaHandlerCallWrapper

faststream.kafka.call_wrapper.KafkaHandlerCallWrapper #

KafkaHandlerCallWrapper(
    call: Callable[P_HandlerParams, T_HandlerReturn],
    outer_config: BrokerConfig,
)

Bases: KafkaCallAssertions, HandlerCallWrapper[P_HandlerParams, T_HandlerReturn]

The wrapper of a Kafka handler: its Call assertions take key and partition.

Initialize a handler.

Source code in faststream/_internal/endpoint/call_wrapper.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
def __init__(
    self,
    call: Callable[P_HandlerParams, T_HandlerReturn],
    outer_config: BrokerConfig,
) -> None:
    """Initialize a handler."""
    self._declared_call = call
    self._composed_call = call
    self._wrapped_call = None

    self._publishers = []
    self._subscribers = []

    self._recorder = CallRecorder(
        getattr(call, "__name__", repr(call)),
        outer_config,
    )
    self.future = None
    self.is_test = False

is_test instance-attribute #

is_test = False

mock property #

mock: MagicMock

The mock recording the endpoint's calls, available under a test broker.

future instance-attribute #

future: Optional[Future[Any]] = None

assert_called_once_with async #

assert_called_once_with(
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
    key: Any = EMPTY,
    partition: Any = EMPTY,
) -> None

Assert the endpoint was called once, with the message described here.

PARAMETER DESCRIPTION
body

The body as a dict, a model or a matcher; it goes through the codec.

TYPE: Any DEFAULT: EMPTY

headers

Headers the message must carry; the rest may carry more.

TYPE: Any DEFAULT: EMPTY

correlation_id

The exact correlation id.

TYPE: Any DEFAULT: EMPTY

reply_to

The exact reply-to destination.

TYPE: Any DEFAULT: EMPTY

content_type

The exact content type.

TYPE: Any DEFAULT: EMPTY

path

The exact path parameters the subject template matched.

TYPE: Any DEFAULT: EMPTY

context

Context paths, as given to Context(), mapped to their values.

TYPE: Mapping[str, Any] DEFAULT: EMPTY

key

The exact record key, as the bytes the client delivered.

TYPE: Any DEFAULT: EMPTY

partition

The exact partition the record was read from.

TYPE: Any DEFAULT: EMPTY

Source code in faststream/_internal/kafka/calls.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
async def assert_called_once_with(
    self,
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
    key: Any = EMPTY,
    partition: Any = EMPTY,
) -> None:
    """Assert the endpoint was called once, with the message described here.

    Args:
        body: The body as a dict, a model or a matcher; it goes through the codec.
        headers: Headers the message must carry; the rest may carry more.
        correlation_id: The exact correlation id.
        reply_to: The exact reply-to destination.
        content_type: The exact content type.
        path: The exact path parameters the subject template matched.
        context: Context paths, as given to `Context()`, mapped to their values.
        key: The exact record key, as the bytes the client delivered.
        partition: The exact partition the record was read from.
    """
    await self._assert_called_once_with(
        self._expected_call(
            body,
            headers=headers,
            correlation_id=correlation_id,
            reply_to=reply_to,
            content_type=content_type,
            path=path,
            context=context,
            key=key,
            partition=partition,
        )
    )

assert_called_with async #

assert_called_with(
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
    key: Any = EMPTY,
    partition: Any = EMPTY,
) -> None

Assert the last message the endpoint saw is the one described here.

PARAMETER DESCRIPTION
body

The body as a dict, a model or a matcher; it goes through the codec.

TYPE: Any DEFAULT: EMPTY

headers

Headers the message must carry; the rest may carry more.

TYPE: Any DEFAULT: EMPTY

correlation_id

The exact correlation id.

TYPE: Any DEFAULT: EMPTY

reply_to

The exact reply-to destination.

TYPE: Any DEFAULT: EMPTY

content_type

The exact content type.

TYPE: Any DEFAULT: EMPTY

path

The exact path parameters the subject template matched.

TYPE: Any DEFAULT: EMPTY

context

Context paths, as given to Context(), mapped to their values.

TYPE: Mapping[str, Any] DEFAULT: EMPTY

key

The exact record key, as the bytes the client delivered.

TYPE: Any DEFAULT: EMPTY

partition

The exact partition the record was read from.

TYPE: Any DEFAULT: EMPTY

Source code in faststream/_internal/kafka/calls.py
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
async def assert_called_with(
    self,
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
    key: Any = EMPTY,
    partition: Any = EMPTY,
) -> None:
    """Assert the last message the endpoint saw is the one described here.

    Args:
        body: The body as a dict, a model or a matcher; it goes through the codec.
        headers: Headers the message must carry; the rest may carry more.
        correlation_id: The exact correlation id.
        reply_to: The exact reply-to destination.
        content_type: The exact content type.
        path: The exact path parameters the subject template matched.
        context: Context paths, as given to `Context()`, mapped to their values.
        key: The exact record key, as the bytes the client delivered.
        partition: The exact partition the record was read from.
    """
    await self._assert_called_with(
        self._expected_call(
            body,
            headers=headers,
            correlation_id=correlation_id,
            reply_to=reply_to,
            content_type=content_type,
            path=path,
            context=context,
            key=key,
            partition=partition,
        )
    )

assert_any_call async #

assert_any_call(
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
    key: Any = EMPTY,
    partition: Any = EMPTY,
) -> None

Assert one of the messages the endpoint saw is the one described here.

PARAMETER DESCRIPTION
body

The body as a dict, a model or a matcher; it goes through the codec.

TYPE: Any DEFAULT: EMPTY

headers

Headers the message must carry; the rest may carry more.

TYPE: Any DEFAULT: EMPTY

correlation_id

The exact correlation id.

TYPE: Any DEFAULT: EMPTY

reply_to

The exact reply-to destination.

TYPE: Any DEFAULT: EMPTY

content_type

The exact content type.

TYPE: Any DEFAULT: EMPTY

path

The exact path parameters the subject template matched.

TYPE: Any DEFAULT: EMPTY

context

Context paths, as given to Context(), mapped to their values.

TYPE: Mapping[str, Any] DEFAULT: EMPTY

key

The exact record key, as the bytes the client delivered.

TYPE: Any DEFAULT: EMPTY

partition

The exact partition the record was read from.

TYPE: Any DEFAULT: EMPTY

Source code in faststream/_internal/kafka/calls.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
async def assert_any_call(
    self,
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
    key: Any = EMPTY,
    partition: Any = EMPTY,
) -> None:
    """Assert one of the messages the endpoint saw is the one described here.

    Args:
        body: The body as a dict, a model or a matcher; it goes through the codec.
        headers: Headers the message must carry; the rest may carry more.
        correlation_id: The exact correlation id.
        reply_to: The exact reply-to destination.
        content_type: The exact content type.
        path: The exact path parameters the subject template matched.
        context: Context paths, as given to `Context()`, mapped to their values.
        key: The exact record key, as the bytes the client delivered.
        partition: The exact partition the record was read from.
    """
    await self._assert_any_call(
        self._expected_call(
            body,
            headers=headers,
            correlation_id=correlation_id,
            reply_to=reply_to,
            content_type=content_type,
            path=path,
            context=context,
            key=key,
            partition=partition,
        )
    )

call_wrapped async #

call_wrapped(message: StreamMessage[Any]) -> Any

Calls the wrapped function with the given message.

Source code in faststream/_internal/endpoint/call_wrapper.py
105
106
107
108
109
110
async def call_wrapped(self, message: "StreamMessage[Any]") -> Any:
    """Calls the wrapped function with the given message."""
    assert self._wrapped_call, "You should use `set_wrapped` first"
    if self.is_test:
        await self._recorder.record(message)
    return await self._wrapped_call(message)

set_wrapped #

set_wrapped(
    *,
    dependencies: Sequence[Dependant],
    _call_decorators: Reversible[Decorator],
    config: FastDependsConfig,
) -> CallModel
Source code in faststream/_internal/endpoint/call_wrapper.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def set_wrapped(
    self,
    *,
    dependencies: Sequence["Dependant"],
    _call_decorators: Reversible["Decorator"],
    config: "FastDependsConfig",
) -> "CallModel":
    # Composed from the declaration rather than from the last composition:
    # `build_call` answers with the call it decorated, so reading that back
    # as the input would decorate it again, one more layer per build.
    dependent = config.build_call(
        self._declared_call,
        dependencies=dependencies,
        call_decorators=_call_decorators,
    )
    self._composed_call = dependent.original_call
    self._wrapped_call = dependent.wrapped_call
    return dependent.dependent

wait_call async #

wait_call(timeout: float | None = None) -> None

Waits for a call with an optional timeout.

Source code in faststream/_internal/endpoint/call_wrapper.py
131
132
133
134
135
async def wait_call(self, timeout: float | None = None) -> None:
    """Waits for a call with an optional timeout."""
    assert self.future is not None, "You can use this method only with TestClient"
    with anyio.fail_after(timeout):
        await self.future

set_test #

set_test() -> None
Source code in faststream/_internal/endpoint/call_wrapper.py
137
138
139
def set_test(self) -> None:
    self.is_test = True
    self.refresh(with_mock=True)

reset_test #

reset_test() -> None
Source code in faststream/_internal/endpoint/call_wrapper.py
141
142
143
144
145
def reset_test(self) -> None:
    self.is_test = False
    self._recorder.reset()
    self._recorder.stop_mirroring()
    self.future = None

trigger #

trigger(
    result: Any = None, error: BaseException | None = None
) -> None
Source code in faststream/_internal/endpoint/call_wrapper.py
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def trigger(
    self,
    result: Any = None,
    error: BaseException | None = None,
) -> None:
    if not self.is_test:
        return

    if self.future is None:
        msg = "You can use this method only with TestClient"
        raise SetupError(msg)

    if self.future.done():
        self.future = asyncio.Future()

    if error:
        self.future.set_exception(error)
        # Mark the mirrored error as retrieved to avoid unhandled-future reports.
        self.future.exception()

    else:
        self.future.set_result(result)

refresh #

refresh(with_mock: bool = False) -> None
Source code in faststream/_internal/endpoint/call_wrapper.py
170
171
172
173
174
175
def refresh(self, with_mock: bool = False) -> None:
    if asyncio.events._get_running_loop() is not None:
        self.future = asyncio.Future()

    if with_mock:
        self._recorder.reset()