-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
Description
Bug report
Bug description:
Bug Description
The in-place OR operator (|=) implementation in ChainMap.__ior__ currently lacks a type check. It unconditionally calls self.maps[0].update(other).
If other is not a mapping or an iterable of pairs (e.g., a custom object intended to handle the operation via __ror__), dict.update raises a TypeError.
This behavior prevents the Python interpreter from falling back to the reflected operator (__ror__) on the right-hand operand, breaking interoperability with custom objects.
This is inconsistent with ChainMap.__or__ (the | operator), which correctly checks if not isinstance(other, Mapping) and returns NotImplemented, allowing the fallback mechanism to work.
Reproduction Steps
Run the following script (tested on main branch 3.15.0a2+):
import sys
from collections import ChainMap
class Rescuer:
def __ror__(self, other):
return "SUCCESS"
print(f"Python Version: {sys.version.split()[0]}")
cm = ChainMap({'a': 1})
r = Rescuer()
print("Testing: cm |= r")
try:
# This should fallback to Rescuer.__ror__ but currently crashes
cm |= r
print(f"Result: {cm}")
except TypeError as e:
print(f"CRASH: Raised TypeError: {e}")Actual Behavior
The script crashes with a TypeError, preventing the fallback.
Testing: cm |= r
CRASH: Raised TypeError: 'Rescuer' object is not iterable
Expected Behavior
The script should output Result: SUCCESS.
ChainMap.__ior__ should catch the TypeError (or check for Mapping type) and return NotImplemented when it encounters an unsupported type. This allows Python to attempt the reflected operation (__ror__) on the other operand.
Python Version
3.15.0a2+ (and 3.11)
CPython versions tested on:
3.11, CPython main branch
Operating systems tested on:
Windows