Skip to content

Commit e061eb1

Browse files
nc9sentrivana
andauthored
fix(arq): handle settings_cls passed as keyword argument (#5393)
The `_sentry_create_worker` patch assumed `settings_cls` is always passed as positional arg (`args[0]`), causing IndexError when users call `create_worker(settings_cls=WorkerSettings)`. Now checks both `args[0]` and `kwargs.get("settings_cls")`. Test added in `tests/integrations/arq/test_arq.py` as `init_arq_with_kwarg_settings` ### Description `settings_cls` is now checked from kwargs if no args ```py settings_cls = args[0] if args else kwargs.get("settings_cls") ``` #### Issues * None --------- Co-authored-by: Ivana Kellyer <ivana.kellyer@sentry.io>
1 parent 30e3f8c commit e061eb1

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

sentry_sdk/integrations/arq.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def patch_create_worker() -> None:
185185

186186
@ensure_integration_enabled(ArqIntegration, old_create_worker)
187187
def _sentry_create_worker(*args: "Any", **kwargs: "Any") -> "Worker":
188-
settings_cls = args[0]
188+
settings_cls = args[0] if args else kwargs.get("settings_cls")
189189

190190
if isinstance(settings_cls, dict):
191191
if "functions" in settings_cls:
@@ -200,13 +200,14 @@ def _sentry_create_worker(*args: "Any", **kwargs: "Any") -> "Worker":
200200
]
201201

202202
if hasattr(settings_cls, "functions"):
203-
settings_cls.functions = [
204-
_get_arq_function(func) for func in settings_cls.functions
203+
settings_cls.functions = [ # type: ignore[union-attr]
204+
_get_arq_function(func)
205+
for func in settings_cls.functions # type: ignore[union-attr]
205206
]
206207
if hasattr(settings_cls, "cron_jobs"):
207-
settings_cls.cron_jobs = [
208+
settings_cls.cron_jobs = [ # type: ignore[union-attr]
208209
_get_arq_cron_job(cron_job)
209-
for cron_job in (settings_cls.cron_jobs or [])
210+
for cron_job in (settings_cls.cron_jobs or []) # type: ignore[union-attr]
210211
]
211212

212213
if "functions" in kwargs:

tests/integrations/arq/test_arq.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,58 @@ def inner(
131131
return inner
132132

133133

134+
@pytest.fixture
135+
def init_arq_with_kwarg_settings(sentry_init):
136+
"""Test fixture that passes settings_cls as keyword argument only."""
137+
138+
def inner(
139+
cls_functions=None,
140+
cls_cron_jobs=None,
141+
kw_functions=None,
142+
kw_cron_jobs=None,
143+
allow_abort_jobs_=False,
144+
):
145+
cls_functions = cls_functions or []
146+
cls_cron_jobs = cls_cron_jobs or []
147+
148+
kwargs = {}
149+
if kw_functions is not None:
150+
kwargs["functions"] = kw_functions
151+
if kw_cron_jobs is not None:
152+
kwargs["cron_jobs"] = kw_cron_jobs
153+
154+
sentry_init(
155+
integrations=[ArqIntegration()],
156+
traces_sample_rate=1.0,
157+
send_default_pii=True,
158+
)
159+
160+
server = FakeRedis()
161+
pool = ArqRedis(pool_or_conn=server.connection_pool)
162+
163+
class WorkerSettings:
164+
functions = cls_functions
165+
cron_jobs = cls_cron_jobs
166+
redis_pool = pool
167+
allow_abort_jobs = allow_abort_jobs_
168+
169+
if not WorkerSettings.functions:
170+
del WorkerSettings.functions
171+
if not WorkerSettings.cron_jobs:
172+
del WorkerSettings.cron_jobs
173+
174+
# Pass settings_cls as keyword argument (not positional)
175+
worker = arq.worker.create_worker(settings_cls=WorkerSettings, **kwargs)
176+
177+
return pool, worker
178+
179+
return inner
180+
181+
134182
@pytest.mark.asyncio
135183
@pytest.mark.parametrize(
136-
"init_arq_settings", ["init_arq", "init_arq_with_dict_settings"]
184+
"init_arq_settings",
185+
["init_arq", "init_arq_with_dict_settings", "init_arq_with_kwarg_settings"],
137186
)
138187
async def test_job_result(init_arq_settings, request):
139188
async def increase(ctx, num):

0 commit comments

Comments
 (0)