id summary reporter owner description type status component version severity resolution keywords cc stage has_patch needs_docs needs_tests needs_better_patch easy ui_ux 33410 captureOnCommitCallbacks executes callbacks multiple times. Petter Friberg Petter Friberg "When recursively adding multiple on commit callbacks, `captureOnCommitCallbacks` executes some callbacks multiple times. Below is a test case to reproduce the error. Patch: https://github.com/django/django/pull/15285 {{{ #!div style=""font-size: 80%"" {{{#!python def test_execute_tree(self): """""" A visualisation of the callback tree tested. Each node is expected to be visited only once. The child count of a node symbolises the amount of on commit callbacks. root └── branch_1 ├── branch_2 │ ├── leaf_1 │ └── leaf_2 └── leaf_3 """""" ( branch_1_call_counter, branch_2_call_counter, leaf_1_call_counter, leaf_2_call_counter, leaf_3_call_counter, ) = [itertools.count(start=1) for _ in range(5)] def leaf_3(): next(leaf_3_call_counter) def leaf_2(): next(leaf_2_call_counter) def leaf_1(): next(leaf_1_call_counter) def branch_2(): next(branch_2_call_counter) transaction.on_commit(leaf_1) transaction.on_commit(leaf_2) def branch_1(): next(branch_1_call_counter) transaction.on_commit(branch_2) transaction.on_commit(leaf_3) with self.captureOnCommitCallbacks(execute=True) as callbacks: with transaction.atomic(): transaction.on_commit(branch_1) # Every counter shall only have been called once, starting at 1; next value then # has to be 2 self.assertEqual(next(branch_1_call_counter), 2) self.assertEqual(next(branch_2_call_counter), 2) self.assertEqual(next(leaf_1_call_counter), 2) self.assertEqual(next(leaf_2_call_counter), 2) self.assertEqual(next(leaf_3_call_counter), 2) # Make sure all calls can be seen and the execution order is correct self.assertEqual( [(id(callback), callback.__name__) for callback in callbacks], [ (id(branch_1), ""branch_1""), (id(branch_2), ""branch_2""), (id(leaf_3), ""leaf_3""), (id(leaf_1), ""leaf_1""), (id(leaf_2), ""leaf_2""), ], ) }}} }}}" Bug closed Testing framework 4.0 Release blocker fixed captureOnCommitCallbacks Eugene Morozov Adam Johnson Ready for checkin 1 0 0 0 0 0