Skip to content

Commit 665bbb7

Browse files
jawwad-aliclaude
andcommitted
fix(workflows): fan-out max_concurrency .inf falls back to sequential, not crash
_run_fan_out coerces max_concurrency with int() inside except (TypeError, ValueError). int(float('inf')) raises OverflowError, which is not in that tuple, so a YAML 'max_concurrency: .inf' crashed the whole run with an uncaught OverflowError instead of the documented 'cannot be coerced -> sequential' fallback. Add OverflowError to the except tuple (nan already coerced via ValueError). Extends the existing invalid-value parametrization with float('inf')/nan (fails before on inf: OverflowError; passes after: sequential, all items in order). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent faeb956 commit 665bbb7

2 files changed

Lines changed: 12 additions & 5 deletions

File tree

src/specify_cli/workflows/engine.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,17 +1197,19 @@ def _run_fan_out(
11971197
already flipped), so the prefix never drops the actual halting item.
11981198
11991199
``max_concurrency`` is coerced with ``int()``; a value that cannot be
1200-
coerced (``None``, a non-numeric string, …) or that coerces to <= 1 runs
1201-
sequentially, while a numeric string like ``"4"`` or a float like ``4.0``
1202-
is honored.
1200+
coerced (``None``, a non-numeric string, ``.inf``/``.nan``, …) or that
1201+
coerces to <= 1 runs sequentially, while a numeric string like ``"4"`` or
1202+
a float like ``4.0`` is honored.
12031203
"""
12041204
if not items:
12051205
return []
12061206

12071207
halting = (RunStatus.PAUSED, RunStatus.FAILED, RunStatus.ABORTED)
12081208
try:
12091209
workers = max(1, int(max_concurrency))
1210-
except (TypeError, ValueError):
1210+
except (TypeError, ValueError, OverflowError):
1211+
# OverflowError: int(float("inf")) — a YAML ``max_concurrency: .inf``
1212+
# would otherwise crash the whole run instead of falling back.
12111213
workers = 1
12121214
# Never spin up more workers than there is work — bounds a user-controlled
12131215
# max_concurrency from over-allocating threads.

tests/test_workflows.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2662,8 +2662,13 @@ def on_item(item):
26622662
results, _ = self._run(tmp_path, list(range(n)), n, on_item)
26632663
assert results == [{"seen": i} for i in range(n)]
26642664

2665-
@pytest.mark.parametrize("bad", [0, -1, None, "abc", 1.0])
2665+
@pytest.mark.parametrize(
2666+
"bad", [0, -1, None, "abc", 1.0, float("inf"), float("nan")]
2667+
)
26662668
def test_invalid_max_concurrency_coerces_to_sequential(self, tmp_path, bad):
2669+
# float("inf") -> int() raises OverflowError (not TypeError/ValueError);
2670+
# it must fall back to sequential like any other uncoercible value, not
2671+
# crash the run.
26672672
results, _ = self._run(tmp_path, list(range(4)), bad)
26682673
assert results == [{"seen": i} for i in range(4)]
26692674

0 commit comments

Comments
 (0)