Use a heap counter to avoid comparing dictionary payloads on ties
Use a heap counter to avoid comparing dictionary payloads on ties
Direct answer: put a unique, increasing counter between the priority and the dictionary: (priority, counter, payload). Equal priorities then compare counters, so Python never needs to order the mappings.
A heap compares its entries with <. With (2, {"job": "A"}) already present, pushing (2, {"job": "B"}) reaches the second tuple elements because the priorities tie. Dictionaries have no ordering relation, so the push raises TypeError. The first half of the fixture catches and records that expected failure.
The repaired queue uses itertools.count() to give every entry a distinct integer. The three inputs deliberately include equal-priority jobs A and B, followed by lower-priority job C. Pops return C first because priority 1 is smaller, then A and B in insertion order because their counters are 0 and 1. The assertions validate that deterministic result for this in-memory fixture, but do not make payloads sortable elsewhere or implement cancellation and priority updates.
The heapq priority-queue notes recommend an entry count as a tie-breaker for precisely this case. heapq and itertools.count() are available in all supported Python 3 versions.
AI-assistance disclosure: Batu Lab Notes used AI assistance to draft this synthetic example and explanation.
Example
from heapq import heappop, heappush
from itertools import count
broken = []
heappush(broken, (2, {"job": "A"}))
try:
heappush(broken, (2, {"job": "B"}))
except TypeError as error:
print(f"broken: {type(error).__name__}")
counter = count()
queue = []
for priority, payload in (
(2, {"job": "A"}),
(2, {"job": "B"}),
(1, {"job": "C"}),
):
heappush(queue, (priority, next(counter), payload))
order = [heappop(queue)[2]["job"] for _ in range(len(queue))]
assert order == ["C", "A", "B"]
print(f"fixed: {order}")
Expected output:
broken: TypeError
fixed: ['C', 'A', 'B']