diff --git a/cassandra/util.py b/cassandra/util.py index 593c264033..e420a382b0 100644 --- a/cassandra/util.py +++ b/cassandra/util.py @@ -787,7 +787,13 @@ def _insert_unchecked(self, key, flat_key, value): self._index[flat_key] = len(self._items) - 1 def _serialize_key(self, key): - return self.cass_key_type.serialize(key, self.protocol_version) + try: + return self.cass_key_type.serialize(key, self.protocol_version) + except Exception: + # A key that cannot be serialized with the map's key type cannot + # be present, so treat it as missing to keep Mapping semantics + # (get() returns the default, `in` returns False). + raise KeyError(str(key)) from None @total_ordering diff --git a/tests/unit/test_orderedmap.py b/tests/unit/test_orderedmap.py index 156bbd5f30..85d5aed6fa 100644 --- a/tests/unit/test_orderedmap.py +++ b/tests/unit/test_orderedmap.py @@ -184,3 +184,16 @@ def test_normalized_lookup(self): assert om[{'one': 1}] is om[{u'one': 1}] assert om[{'two': 2}] is om[{u'two': 2}] assert om[{'one': 1}] is not om[{'two': 2}] + + def test_unserializable_key_treated_as_missing(self): + # a key that cannot be serialized with the map's key type cannot be + # present, so lookups behave like a plain dict instead of leaking the + # serializer's exception + om = OrderedMapSerializedKey(UTF8Type, 3) + om._insert_unchecked('one', UTF8Type.serialize('one', 3), 1) + + assert om.get(None) is None + assert om.get(None, 2) == 2 + assert None not in om + with pytest.raises(KeyError): + om[None]