Repository navigation
Conversation
succeeded() and get_results() also required a non-None result, so a branch that returned None counted towards success_count but was missing from both. failed() and get_errors() had the same check on the error. Select items by status only. When replay rebuilds a FAILED item from a child context checkpoint without an error, record the generic ChildContextError that replaying that child context raises, so every FAILED item still has an error. Closes aws#760
| for item in self.all | ||
| if item.status is BatchItemStatus.FAILED and item.error is not None | ||
| ] | ||
| return [cast("ErrorObject", item.error) for item in self.failed()] |
There was a problem hiding this comment.
cast() only changes static typing; it leaves None unchanged. BatchItem(..., FAILED, error=None) remains accepted (including in test_batch_result_failed_with_none_error), and BatchResult.from_dict() also permits it. These paths bypass _failed_checkpoint_error_object(), so get_errors() can return [None] despite its list[ErrorObject] contract. I reproduced this after a default ExtendedTypeSerDes round trip; accessing error.type then raises AttributeError.
Could we normalize missing failed-item errors at the model/deserialization boundary using the same generic ChildContextError, and extend the regression test to cover get_errors() after deserialization? That would preserve one error per failed item while making the return type accurate.
There was a problem hiding this comment.
Good catch — cast() was only papering over the typing hole.
I normalized missing FAILED-item errors at the model boundary (BatchItem.__post_init__ / from_dict), using the same generic ChildContextError message the executor already records via _failed_checkpoint_error_object when a child-context checkpoint has no ErrorObject. get_errors() still falls back defensively.
Extended test_batch_result_failed_with_none_error to assert get_errors() after construction, after from_dict of an error: null wire payload, and after an ExtendedTypeSerDes round-trip of that same null-error payload (the path that was raising AttributeError on error.type).
FAILED BatchItems constructed or deserialized without an ErrorObject now receive the same generic ChildContextError the executor records for a FAILED child-context checkpoint with no error. Extends the regression test to cover get_errors() after from_dict and ExtendedTypeSerDes. Addresses review feedback on aws#765.
Issue #, if available:: Closes #760
Description of changes:
succeeded()andget_results()also checkeditem.result is not None, so a branch that returnedNonewas counted insuccess_countbut dropped from both.failed()andget_errors()had the same check onitem.error.Following the approach suggested in #760:
succeeded()andfailed()select items by status alone.get_results()andget_errors()are built from them with acast, so the return types staylist[R]andlist[ErrorObject]_replay_terminal_itemand_replay_from_checkpoints), it now records the genericChildContextErrorthat replaying that child context raises. Every FAILED item has an error, andthrow_if_error()raises for ittest_batch_result_failed_with_none_errorasserted the old filter, so it now expects the FAILED item to be keptFor the release notes:
get_results()can now containNonewhen a branch returns nothing, so something likesum(batch.get_results())raises in that case.Testing:
BatchResultwithNoneresults, a liveexecute()over branches returning[None, 10, None, 30], and both replay paths with a FAILED checkpoint that has no errorhatch run dev-core:cov: 1769 passed, 98.23% coveragehatch run test:all: 4080 passed, 2 skippedhatch run types:checkandhatch fmt --checkin the core package: passedBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.