Skip to content

Commit c9de598

Browse files
committed
Preserve descendant subtrees when reprioritizing
Keep the moved descendant attached to its own children during cycle avoidance, as required by RFC 7540 section 5.3.3. Cover direct and indirect descendants with exclusive and nonexclusive dependencies, including child-list and queue consistency. Generated with OpenAI Codex and independently reviewed by a native AI agent. No human review or certification is claimed.
1 parent 532ace5 commit c9de598

2 files changed

Lines changed: 48 additions & 1 deletion

File tree

‎src/priority/priority.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ def reprioritize(
428428
# continue.
429429
if cycle:
430430
new_parent.parent.remove_child( # type: ignore[union-attr]
431-
new_parent,
431+
new_parent, strip_children=False
432432
)
433433
current_stream.parent.add_child( # type: ignore[union-attr]
434434
new_parent,

‎test/test_priority.py‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,53 @@ def test_can_reprioritize_a_stream(
252252
actual_result = [next(t) for _ in range(len(result))]
253253
assert actual_result == result
254254

255+
@pytest.mark.parametrize("exclusive", [True, False])
256+
@pytest.mark.parametrize("descendant_parent", [1, 5])
257+
def test_reprioritize_preserves_descendant_children(
258+
self, exclusive, descendant_parent
259+
):
260+
"""
261+
Moving a descendant to avoid a cycle keeps its subtree intact.
262+
"""
263+
p = priority.PriorityTree()
264+
# RFC 7540 Figure 5: A=1, B=3, C=5, D=7, E=9, F=11.
265+
for stream_id, parent in [
266+
(1, 0),
267+
(3, 1),
268+
(5, 1),
269+
(7, descendant_parent),
270+
(9, 5),
271+
(11, 7),
272+
]:
273+
p.insert_stream(stream_id, depends_on=parent)
274+
275+
p.reprioritize(1, depends_on=7, exclusive=exclusive)
276+
277+
assert {
278+
stream_id: stream.parent.stream_id
279+
for stream_id, stream in p._streams.items()
280+
if stream_id != 0
281+
} == {1: 7, 3: 1, 5: 1, 7: 0, 9: 5, 11: 1 if exclusive else 7}
282+
283+
for stream in p._streams.values():
284+
expected_children = sorted(
285+
child.stream_id
286+
for child in p._streams.values()
287+
if child.parent is stream
288+
)
289+
assert (
290+
sorted(child.stream_id for child in stream.children)
291+
== expected_children
292+
)
293+
assert (
294+
sorted(child.stream_id for _, child in stream.child_queue)
295+
== expected_children
296+
)
297+
298+
p.block(7)
299+
expected = [1] * 10 if exclusive else [1, 11] * 5
300+
assert [next(p) for _ in range(10)] == expected
301+
255302
def test_priority_tree_raises_error_inserting_duplicate(self):
256303
"""
257304
Attempting to insert a stream that is already in the tree raises a

0 commit comments

Comments
 (0)