Source code for trol.util

"""A set of utility functions for use in multiple parts of trol

This module currently contains the serialize and deserialize methods for the Property and Collection classes I implement

>>> import redis
>>> import trol
...
>>> class HotNewClass:
...     def __init__(self, howhot):
...         self.howhot = howhot
...
>>> @trol.serializer(HotNewClass)
... def hotnew_serializer(hnc):
...     print("HNC IS BEING SERIALIZED!")
...     return '<HOT>{}'.format(hnc.howhot)
...
>>> @trol.deserializer(HotNewClass)
... def hotnew_deserializer(byts):
...     print("RETURN OF THE HNC!")
...     howhot = int(byts.decode('utf-8').strip('<HOT>'))
...     return HotNewClass(howhot)
...
>>> class SweetModel(trol.Model):
...     def __init__(self, ident, redis):
...         self.id = ident
...         self.redis = redis
...
...     bar = trol.Property(typ=HotNewClass)
...
>>> r = redis.Redis('localhost')
>>> sm = SweetModel('xyz', r)
>>> sm.bar = HotNewClass(10)
HNC IS BEING SERIALIZED!
>>> r.get(sm.key + ':bar')
b'<HOT>10'
>>> sm.invalidate()
>>> sm.bar.howhot
RETURN OF THE HNC!
10
>>> r.flushall()
True

"""

import weakref
import trol


def serialize_str(obj):
    return obj

def serialize_int(obj):
    return obj

def serialize_float(obj):
    return obj

def serialize_bytes(obj):
    return obj

def serialize_bool(obj):
    if obj:
        return b'True'
    else:
        return b'False'

serializers = {
    str: serialize_str,
    int: serialize_int,
    float: serialize_float,
    bytes: serialize_bytes,
    bool: serialize_bool,
}
""" dict[type, Callable[[object], bytes]]: A dictionary of serializers known trol classes

Additonal entries can be added to support new serializable types
"""


[docs]def serializer(cls): """A convinience decorator to register a serializer""" def decorator(f): serializers[cls] = f return f return decorator
[docs]class Serializer: """A class containing the provided serialize functions for selected type The serializers here are aim for human-readability, which means they are not their most optimized If you want better performance through avoidance to and from `str`, implement a new serializer Attributes: func (Callable[[object], object]: The serialization function this class is constructed to use The input and return types are determined by the type used to construct this object The output type will be a serial type accepted by redis-py Args: typ (type): The type of objects which will be serialized by this Serializer Currently supported types are: `str`, `int`, `float`, and `bytes` """ def __init__(self, typ): try: self.func = serializers[typ] except KeyError: raise ValueError("{} is not supported".format(typ.__name__)) def __call__(self, obj): """Serialize the input object into a form acceptable to redis-py Args: obj (object): An object of the same type used to construct this Serializer Returns: object: A serialized version acceptable to redis-py """ return self.func(obj)
def deserialize_str(byts): return byts.decode('utf-8') def deserialize_int(byts): return int(byts.decode('utf-8')) def deserialize_float(byts): return float(byts.decode('utf-8')) def deserialize_bytes(byts): return byts def deserialize_bool(byts): if byts == b'True': return True else: return False deserializers = { str: deserialize_str, int: deserialize_int, float: deserialize_float, bytes: deserialize_bytes, bool: deserialize_bool } """ dict[type, Callable[[bytes], object]]: A dictionary of deserializers known trol classes Additonal entries can be added to support new deserializable types There should be an entry here for each one in serializers """
[docs]def deserializer(cls): """A convinience decorator to register a deserializer""" def decorator(f): deserializers[cls] = f return f return decorator
[docs]class Deserializer: """A class containing the provided deserialize functions for selected type The deserializers here are aim for human-readability, which means they are not their most optimized If you want better performance through avoidance to and from `str`, implement a new deserializer Attributes: func (Callable[[bytes], object]: The deserialization function this class is constructed to use The return type is determined by the type used to construct this object Args: typ (type): The type of objects which will be deserialized by this Deserializer Currently supported types are: `str`, `int`, `float`, and `bytes` """ def __init__(self, typ): try: self.func = deserializers[typ] except KeyError: raise ValueError("{} is not supported".format(typ.__name__)) def __call__(self, obj): """Deserialize the input bytes from redis-py into the desired object type Args: byts (bytes): A bytes object containing the data you want to deserialize Returns: object: An object of the desired type """ return self.func(obj)