Complete a property whose file SharePoint rejected 🟩

Green on arrival — rename() records rejections rather than raising.
Pinned after verifying it bites: letting the rejection escape fails the
child sub_task, which turns the whole Task red.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Daniel Roth 2026-07-29 09:53:58 +00:00
parent 5b1b319c2d
commit 35a3ebe0e3

View file

@ -163,9 +163,7 @@ def _property_subtasks(harness: Harness, result: Any) -> list[SubTask]:
the decorator creates for the run itself."""
wrapper = _subtask_id(result)
return [
s
for s in harness.subtasks.list_by_task(_task_id(result))
if s.id != wrapper
s for s in harness.subtasks.list_by_task(_task_id(result)) if s.id != wrapper
]
@ -349,9 +347,7 @@ def test_run_completes_with_rejected_files_and_missing_folders_listed(
productive run red the failures are the record (ADR-0060)."""
# Arrange
sharepoint = FakeSharepoint(
_one_property_site(
_file("Locked.pdf", "id-1"), _file("Survey.pdf", "id-2")
),
_one_property_site(_file("Locked.pdf", "id-1"), _file("Survey.pdf", "id-2")),
reject={"id-1": PermissionError("locked by another user")},
)
_install(
@ -387,6 +383,35 @@ def test_run_completes_with_rejected_files_and_missing_folders_listed(
}
def test_property_whose_file_was_rejected_completes_rather_than_failing(
harness: Harness, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""A failed child would turn the whole Task red — any failed sub_task does.
A locked file must be recorded on a *completed* property instead."""
# Arrange
sharepoint = FakeSharepoint(
_one_property_site(_file("Locked.pdf", "id-1"), _file("Survey.pdf", "id-2")),
reject={"id-1": PermissionError("locked by another user")},
)
_install(monkeypatch, tmp_path, sharepoint)
# Act
result = _handler(harness)(_sqs_event({"sharepoint_site": SITE}), None)
# Assert
child = _property_subtasks(harness, result)[0]
assert child.status is SubTaskStatus.COMPLETE
assert (child.outputs or {})["result"]["failed"] == [
{
"uprn": UPRN,
"original_name": "Locked.pdf",
"new_name": f"{UPRN}_{ADDRESS} {POSTCODE}_Locked.pdf",
"error": "locked by another user",
}
]
assert harness.tasks.get(_task_id(result)).status is TaskStatus.COMPLETE
# ---------------------------------------------------------------------------
# An unusable site is rejected before anything is touched
# ---------------------------------------------------------------------------
@ -426,5 +451,7 @@ def test_unrecognised_site_fails_the_run(
# Assert
subtask = harness.subtasks.get(_subtask_id(result))
assert subtask.status is SubTaskStatus.FAILED
assert "Unrecognised SharePoint site 'NOT_A_SITE'" in (subtask.outputs or {})["error"]
assert (
"Unrecognised SharePoint site 'NOT_A_SITE'" in (subtask.outputs or {})["error"]
)
assert sharepoint.renamed == []