Skip to content

Commit 8657814

Browse files
authored
Added warnings on parsing errors. (#410)
1 parent 8e14595 commit 8657814

File tree

2 files changed

+277
-2
lines changed

2 files changed

+277
-2
lines changed

taskiq/receiver/params_parser.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,13 @@ def parse_params(
7676
# trying to parse found value as in type annotation.
7777
message.args[argnum] = parse_obj_as(annot, value)
7878
except (ValueError, RuntimeError) as exc:
79-
logger.debug(exc, exc_info=True)
79+
logger.warning(
80+
"Can't parse argument %d for task %s. Reason: %s",
81+
argnum,
82+
message.task_name,
83+
exc,
84+
exc_info=True,
85+
)
8086
else:
8187
# We try to get this parameter from kwargs.
8288
value = message.kwargs.get(param_name)
@@ -86,4 +92,10 @@ def parse_params(
8692
# trying to parse found value as in type annotation.
8793
message.kwargs[param_name] = parse_obj_as(annot, value)
8894
except (ValueError, RuntimeError) as exc:
89-
logger.debug(exc, exc_info=True)
95+
logger.warning(
96+
"Can't parse argument %s for task %s. Reason: %s",
97+
param_name,
98+
message.task_name,
99+
exc,
100+
exc_info=True,
101+
)

tests/receiver/test_params_parser.py

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
import inspect
2+
import logging
3+
from dataclasses import dataclass
4+
from typing import Any, Callable, get_type_hints
5+
6+
import pytest
7+
from pydantic import BaseModel
8+
9+
from taskiq.message import TaskiqMessage
10+
from taskiq.receiver.params_parser import parse_params
11+
12+
13+
def _helper(f: Callable[..., Any], message: TaskiqMessage) -> None:
14+
sign = inspect.signature(f)
15+
hints = get_type_hints(f)
16+
parse_params(sign, hints, message)
17+
18+
19+
def test_primitive_args_success() -> None:
20+
def func(a: int, b: int) -> None:
21+
pass
22+
23+
msg = TaskiqMessage(
24+
task_id="test",
25+
task_name="test",
26+
labels={},
27+
labels_types={},
28+
args=["1", "2"],
29+
kwargs={},
30+
)
31+
_helper(func, msg)
32+
assert msg.args == [1, 2]
33+
assert msg.kwargs == {}
34+
35+
36+
def test_dataclasses_args_success() -> None:
37+
@dataclass
38+
class TestObj:
39+
a: int
40+
b: int
41+
42+
def func(a: TestObj) -> None:
43+
pass
44+
45+
msg = TaskiqMessage(
46+
task_id="test",
47+
task_name="test",
48+
labels={},
49+
labels_types={},
50+
args=[{"a": "10", "b": "20"}],
51+
kwargs={},
52+
)
53+
_helper(func, msg)
54+
assert msg.args == [TestObj(a=10, b=20)]
55+
assert msg.kwargs == {}
56+
57+
58+
def test_pydantic_args_success() -> None:
59+
class TestObj(BaseModel):
60+
a: int
61+
b: int
62+
63+
def func(a: TestObj) -> None:
64+
pass
65+
66+
msg = TaskiqMessage(
67+
task_id="test",
68+
task_name="test",
69+
labels={},
70+
labels_types={},
71+
args=[{"a": "10", "b": "20"}],
72+
kwargs={},
73+
)
74+
_helper(func, msg)
75+
assert msg.args == [TestObj(a=10, b=20)]
76+
assert msg.kwargs == {}
77+
78+
79+
def test_primitive_args_failure(caplog: pytest.LogCaptureFixture) -> None:
80+
def func(a: int, b: int) -> None:
81+
pass
82+
83+
msg = TaskiqMessage(
84+
task_id="test",
85+
task_name="test",
86+
labels={},
87+
labels_types={},
88+
args=["f3", "2"],
89+
kwargs={},
90+
)
91+
with caplog.at_level(logging.WARNING):
92+
_helper(func, msg)
93+
assert "Can't parse argument 0" in caplog.text
94+
assert msg.args == ["f3", 2]
95+
96+
97+
def test_dataclasses_args_failure(caplog: pytest.LogCaptureFixture) -> None:
98+
@dataclass
99+
class TestObj:
100+
a: int
101+
b: int
102+
103+
def func(a: TestObj) -> None:
104+
pass
105+
106+
msg = TaskiqMessage(
107+
task_id="test",
108+
task_name="test",
109+
labels={},
110+
labels_types={},
111+
args=[{"a": "10", "b": "f3"}],
112+
kwargs={},
113+
)
114+
with caplog.at_level(logging.WARNING):
115+
_helper(func, msg)
116+
assert "Can't parse argument 0" in caplog.text
117+
assert msg.args == [{"a": "10", "b": "f3"}]
118+
119+
120+
def test_pyndantic_args_failure(caplog: pytest.LogCaptureFixture) -> None:
121+
class TestObj(BaseModel):
122+
a: int
123+
b: int
124+
125+
def func(a: TestObj) -> None:
126+
pass
127+
128+
msg = TaskiqMessage(
129+
task_id="test",
130+
task_name="test",
131+
labels={},
132+
labels_types={},
133+
args=[{"a": "10", "b": "f3"}],
134+
kwargs={},
135+
)
136+
137+
with caplog.at_level(logging.WARNING):
138+
_helper(func, msg)
139+
assert "Can't parse argument 0" in caplog.text
140+
assert msg.args == [{"a": "10", "b": "f3"}]
141+
142+
143+
def test_kwargs_primitives_success() -> None:
144+
def func(a: int, b: int) -> None:
145+
pass
146+
147+
msg = TaskiqMessage(
148+
task_id="test",
149+
task_name="test",
150+
labels={},
151+
labels_types={},
152+
args=[1],
153+
kwargs={"b": "2"},
154+
)
155+
_helper(func, msg)
156+
assert msg.args == [1]
157+
assert msg.kwargs == {"b": 2}
158+
159+
160+
def test_kwargs_dataclasses_success() -> None:
161+
@dataclass
162+
class TestObj:
163+
a: int
164+
b: int
165+
166+
def func(a: TestObj) -> None:
167+
pass
168+
169+
msg = TaskiqMessage(
170+
task_id="test",
171+
task_name="test",
172+
labels={},
173+
labels_types={},
174+
args=[],
175+
kwargs={"a": {"a": "10", "b": "20"}},
176+
)
177+
_helper(func, msg)
178+
assert msg.args == []
179+
assert msg.kwargs == {"a": TestObj(a=10, b=20)}
180+
181+
182+
def test_kwargs_pyndantic_success() -> None:
183+
class TestObj(BaseModel):
184+
a: int
185+
b: int
186+
187+
def func(a: TestObj) -> None:
188+
pass
189+
190+
msg = TaskiqMessage(
191+
task_id="test",
192+
task_name="test",
193+
labels={},
194+
labels_types={},
195+
args=[],
196+
kwargs={"a": {"a": "10", "b": "20"}},
197+
)
198+
_helper(func, msg)
199+
assert msg.args == []
200+
assert msg.kwargs == {"a": TestObj(a=10, b=20)}
201+
202+
203+
def test_kwargs_primitives_failure(caplog: pytest.LogCaptureFixture) -> None:
204+
def func(a: int, b: int) -> None:
205+
pass
206+
207+
msg = TaskiqMessage(
208+
task_id="test",
209+
task_name="test",
210+
labels={},
211+
labels_types={},
212+
args=[],
213+
kwargs={"a": "1", "b": "f3"},
214+
)
215+
with caplog.at_level(logging.WARNING):
216+
_helper(func, msg)
217+
assert "Can't parse argument b" in caplog.text
218+
assert msg.kwargs == {"a": 1, "b": "f3"}
219+
220+
221+
def test_kwargs_dataclasses_failure(caplog: pytest.LogCaptureFixture) -> None:
222+
@dataclass
223+
class TestObj:
224+
a: int
225+
b: int
226+
227+
def func(a: TestObj) -> None:
228+
pass
229+
230+
msg = TaskiqMessage(
231+
task_id="test",
232+
task_name="test",
233+
labels={},
234+
labels_types={},
235+
args=[],
236+
kwargs={"a": {"a": "10", "b": "f3"}},
237+
)
238+
with caplog.at_level(logging.WARNING):
239+
_helper(func, msg)
240+
assert "Can't parse argument a" in caplog.text
241+
assert msg.kwargs == {"a": {"a": "10", "b": "f3"}}
242+
243+
244+
def test_kwargs_pyndantic_failure(caplog: pytest.LogCaptureFixture) -> None:
245+
class TestObj(BaseModel):
246+
a: int
247+
b: int
248+
249+
def func(a: TestObj) -> None:
250+
pass
251+
252+
msg = TaskiqMessage(
253+
task_id="test",
254+
task_name="test",
255+
labels={},
256+
labels_types={},
257+
args=[],
258+
kwargs={"a": {"a": "10", "b": "f3"}},
259+
)
260+
with caplog.at_level(logging.WARNING):
261+
_helper(func, msg)
262+
assert "Can't parse argument a" in caplog.text
263+
assert msg.kwargs == {"a": {"a": "10", "b": "f3"}}

0 commit comments

Comments
 (0)