collective.redismemoize.serializer#
The check that decides what is shareable, and the restricted pickle format.
Strict serialization of plain data.
A value goes to Redis only when it is plain data, and that is decided by
construction: dumps() walks the value and accepts nothing but the types
listed here, matched exactly. "pickle.dumps did not raise" is not the test.
A persistent object without an acquisition wrapper pickles happily and comes
back as a detached copy, and a utility comes back as a different object.
Neither is an error pickle can report, and both break the caller.
loads() is the security boundary. Its unpickler resolves only the
globals the accepted types need, so a payload someone else wrote into Redis
cannot make this process call anything.
This module is pure Python and never imports Zope; DateTime is a plain
library.
- collective.redismemoize.serializer.FORMAT_VERSION = b'\x01'#
First byte of every payload. A future format gets a new byte, and a payload with a byte this code does not know is treated as a miss.
- collective.redismemoize.serializer.PROTOCOL = 5#
Pickle protocol used for every payload.
- collective.redismemoize.serializer.LEAVES: frozenset[type] = frozenset({<class 'DateTime.DateTime.DateTime'>, <class 'NoneType'>, <class 'bool'>, <class 'bytearray'>, <class 'bytes'>, <class 'complex'>, <class 'datetime.date'>, <class 'datetime.datetime'>, <class 'datetime.time'>, <class 'datetime.timedelta'>, <class 'datetime.timezone'>, <class 'decimal.Decimal'>, <class 'float'>, <class 'int'>, <class 'str'>, <class 'uuid.UUID'>})#
Types accepted as leaves, matched with
type(value) in LEAVES.
- collective.redismemoize.serializer.SEQUENCES: frozenset[type] = frozenset({<class 'frozenset'>, <class 'list'>, <class 'set'>, <class 'tuple'>})#
Containers accepted, walked recursively, matched exactly.
- collective.redismemoize.serializer.SAFE_GLOBALS: frozenset[tuple[str, str]] = frozenset({('DateTime.DateTime', 'DateTime'), ('builtins', 'complex'), ('datetime', 'date'), ('datetime', 'datetime'), ('datetime', 'time'), ('datetime', 'timedelta'), ('datetime', 'timezone'), ('decimal', 'Decimal'), ('uuid', 'UUID')})#
The globals
loads()may resolve, as(module, name). Exactly what pickling the types inLEAVESproduces, and nothing else.
Bases:
TypeErrorA value that is not plain data, and so stays in the RAM cache.
- Parameters:
reason -- What was refused and where, for the log.
- Parameters:
reason (str)
- exception collective.redismemoize.serializer.UndecodableValue[source]#
Bases:
ValueErrorA payload
loads()refuses to decode; callers treat it as a miss.
- collective.redismemoize.serializer.check(value, path='value')[source]#
Refuse anything that is not plain data.
- Parameters:
- Raises:
NotShareable -- Naming the offending type and its path.
- Return type:
None
- collective.redismemoize.serializer.dumps(value)[source]#
Serialize plain data.
- Parameters:
value (object) -- The value to store.
- Returns:
The payload, starting with
FORMAT_VERSION.- Raises:
NotShareable -- When the value is not plain data.
- Return type:
- collective.redismemoize.serializer.loads(payload)[source]#
Decode a payload written by
dumps().- Parameters:
payload (bytes) -- The bytes read from Redis.
- Returns:
A new copy of the stored value.
- Raises:
UndecodableValue -- For an unknown format, a truncated or corrupt payload, or one that asks for a global not in
SAFE_GLOBALS.- Return type: