sider.types — Conversion between Python and Redis types

In Redis all data are byte strings — bulks. Lists are lists of byte strings, sets are sets of byte strings, and hashes consist of byte string keys and byte string values.

To store richier objects into Redis we have to encode Python values and decode Redis data. Bulk and its subclasses are for that, it defines two basic methods: encode() and decode(). For example, Integer encodes Python int 3 into Redis bulk "3" and decodes Redis bulk "3" into Python int 3.

Inheritance diagram of sider.types

class sider.types.Boolean

Bases: sider.types.Integer

Stores bool values as '1' or '0'.

>>> boolean = Boolean()
>>> boolean.encode(True)
'1'
>>> boolean.encode(False)
'0'
class sider.types.Bulk

Bases: sider.types.Value

The abstract base class to be subclassed. You have to implement encode() and decode() methods in subclasses.

decode(bulk)

Decodes a Redis bulk to Python object. Every subclass of Bulk must implement this method. By default it raises NotImplementedError.

Parameters:bulk (str) – a Redis bullk to decode into Python object
Returns:a decoded Python object
encode(value)

Encodes a Python value into Redis bulk. Every subclass of Bulk must implement this method. By default it raises NotImplementedError.

Parameters:value – a Python value to encode into Redis bulk
Returns:an encoded Redis bulk
Return type:str
Raises exceptions.TypeError:
 if the type of a given value is not acceptable by this type
class sider.types.ByteString

Bases: sider.types.Bulk

Stores byte strings. It stores the given byte strings as these are. It works simply transparently for str values.

>>> bytestr = ByteString()
>>> bytestr.encode('annyeong')
'annyeong'
>>> bytestr.decode('sayonara')
'sayonara'
class sider.types.Date

Bases: sider.types.Bulk

Stores datetime.date values. Dates are internally formatted in RFC 3339 format e.g. 2012-03-28.

>>> import datetime
>>> date = Date()
>>> date.encode(datetime.date(2012, 3, 28))
'2012-03-28'
>>> date.decode(_)
datetime.date(2012, 3, 28)
DATE_FORMAT = '%Y-%m-%d'

(str) The strftime() format string for RFC 3339.

DATE_PATTERN = <_sre.SRE_Pattern object at 0x3320ff0>

The re pattern that matches to RFC 3339 formatted date string e.g. '2012-03-28'.

class sider.types.DateTime

Bases: sider.types.Bulk

Stores naive datetime.datetime values. Values are internally formatted in RFC 3339 format e.g. 2012-03-28T09:21:34.638972.

>>> dt = DateTime()
>>> dt.decode('2012-03-28T09:21:34.638972')
datetime.datetime(2012, 3, 28, 9, 21, 34, 638972)
>>> dt.encode(_)
'2012-03-28T09:21:34.638972'

It doesn’t store tzinfo data.

>>> from sider.datetime import UTC
>>> decoded = dt.decode('2012-03-28T09:21:34.638972Z')
>>> decoded
datetime.datetime(2012, 3, 28, 9, 21, 34, 638972)
>>> dt.encode(decoded.replace(tzinfo=UTC))
'2012-03-28T09:21:34.638972'

Note

If you must be aware of time zone, use TZDateTime instead.

DATETIME_PATTERN = <_sre.SRE_Pattern object at 0x332b660>
parse_datetime(bulk)

Parses a RFC 3339 formatted string into datetime.datetime.

>>> dt = DateTime()
>>> dt.parse_datetime('2012-03-28T09:21:34.638972')
datetime.datetime(2012, 3, 28, 9, 21, 34, 638972)

Unlike decode() it is aware of tzinfo data if the string contains time zone notation.

>>> a = dt.parse_datetime('2012-03-28T09:21:34.638972Z')
>>> a  
datetime.datetime(2012, 3, 28, 9, 21, 34, 638972,
                  tzinfo=sider.datetime.Utc())
>>> b = dt.parse_datetime('2012-03-28T18:21:34.638972+09:00')
>>> b  
datetime.datetime(2012, 3, 28, 18, 21, 34, 638972,
                  tzinfo=sider.datetime.FixedOffset(540))
>>> a == b
True
Parameters:bulk (basestring) – a RFC 3339 formatted string
Returns:a parsing result
Return type:datetime.datetime

Note

It is for internal use and decode() method actually uses this method.

class sider.types.Hash(key_type=None, value_type=None)

Bases: sider.types.Value

The type object for sider.hash.Hash objects and other collections.Mapping objects.

Parameters:
  • key_type (Bulk, type) – the type of keys the hash will contain. default is ByteString
  • value_type (Bulk, type) – the type of values the hash will contain. default is ByteString
class sider.types.Integer

Bases: sider.types.Bulk

Stores integers as decimal strings. For example:

>>> integer = Integer()
>>> integer.encode(42)
'42'
>>> integer.decode('42')
42

Why it doesn’t store integers as binaries but decimals is that Redis provides INCR, INCRBY, DECR and DECRBY for decimal strings. You can simply add and subtract integers.

class sider.types.List(value_type=None)

Bases: sider.types.Value

The type object for sider.list.List objects and other collections.Sequence objects except strings. (Use ByteString or UnicodeString for strings.)

Parameters:value_type (Bulk, type) – the type of values the list will contain. default is ByteString
class sider.types.Set(value_type=None)

Bases: sider.types.Value

The type object for sider.set.Set objects and other collections.Set objects.

Parameters:value_type (Bulk, type) – the type of values the set will contain. default is ByteString
class sider.types.TZDateTime

Bases: sider.types.DateTime

Similar to DateTime except it accepts only tz-aware datetime.datetime values. All values are internally stored in UTC.

>>> from sider.datetime import FixedOffset
>>> dt = datetime.datetime(2012, 3, 28, 18, 21, 34, 638972,
...                        tzinfo=FixedOffset(540))
>>> tzdt = TZDateTime()
>>> tzdt.encode(dt)
'2012-03-28T09:21:34.638972Z'
>>> tzdt.decode(_)  
datetime.datetime(2012, 3, 28, 9, 21, 34, 638972,
                  tzinfo=sider.datetime.Utc())

If any naive datetime.datetime has passed it will raise ValueError.

class sider.types.UnicodeString

Bases: sider.types.Bulk

Stores Unicode strings (unicode), not byte strings (str). Internally all Unicode strings are encoded into and decoded from UTF-8 byte strings.

>>> unistr = UnicodeString()
>>> unistr.encode(u'\uc720\ub2c8\ucf54\ub4dc')
'\xec\x9c\xa0\xeb\x8b\x88\xec\xbd\x94\xeb\x93\x9c'
>>> unistr.decode(_)
u'\uc720\ub2c8\ucf54\ub4dc'
class sider.types.Value

Bases: object

There are two layers behind Sider types: the lower one is this Value and the higher one is Bulk.

Value types can be set to Redis keys, but unlike Bulk it cannot be a value type of other rich Value types e.g. List, Hash.

In most cases you (users) don’t have to subclass Value, and should not. Direct subclasses of Value aren’t about encodings/decodings of Python object but simply Python-side representations of Redis types. It actually doesn’t have methods like encode() and decode(). These methods appear under Bulk or its subtypes.

But it’s about how to save Python objects into Redis keys and how to load values from associated Redis keys. There are several commands to save like SET, MSET, HSET, RPUSH and the rest in Redis and subtypes have to decide which command of those to use.

All subtypes of Value implement save_value() and load_value() methods. The constructor which takes no arguments have to be implemented as well.

classmethod ensure_value_type(value_type, parameter=None)

Raises a TypeError if the given value_type is not an instance of nor a subclass of the class.

>>> Integer.ensure_value_type(Bulk
... )  
Traceback (most recent call last):
  ...
TypeError: expected a subtype of sider.types.Integer,
           but sider.types.Bulk was passed
>>> Integer.ensure_value_type(UnicodeString()
... )  
Traceback (most recent call last):
  ...
TypeError: expected an instance of sider.types.Integer,
           but <sider.types.UnicodeString object at ...>
           was passed
>>> Bulk.ensure_value_type(1)
Traceback (most recent call last):
  ...
TypeError: expected a type, not 1

Otherwise it simply returns an instance of the given value_type.

>>> Bulk.ensure_value_type(Bulk)  
<sider.types.Bulk object at ...>
>>> Bulk.ensure_value_type(ByteString)  
<sider.types.ByteString object at ...>
>>> ByteString.ensure_value_type(ByteString
... )  
<sider.types.ByteString object at ...>
>>> bytestr = ByteString()
>>> ByteString.ensure_value_type(bytestr) 
<sider.types.ByteString object at ...>

If an optional parameter name has present, the error message becomes better.

>>> Integer.ensure_value_type(Bulk,
...   parameter='argname')  
Traceback (most recent call last):
  ...
TypeError: argname must be a subtype of sider.types.Integer,
           but sider.types.Bulk was passed
>>> Integer.ensure_value_type(UnicodeString(),
...   parameter='argname'
... )  
Traceback (most recent call last):
  ...
TypeError: argname must be an instance of sider.types.Integer,
           but <sider.types.UnicodeString object at ...>
           was passed
>>> Bulk.ensure_value_type(1, parameter='argname')
Traceback (most recent call last):
  ...
TypeError: argname must be a type, not 1
Parameters:
  • value_type (Value, type) – a type expected to be a subtype of the class
  • parameter (str) – an optional parameter name. if present the error message becomes better
Raises exceptions.TypeError:
 

if the given subtype is not a subclass of the class

load_value(session, key)

How to load the value from the given Redis key. Subclasses have to implement it. By default it raises NotImplementedError.

Parameters:
  • session (sider.session.Session) – the session object that stores the given key
  • key (str) – the key name to load
Returns:

the Python representation of the loaded value

save_value(session, key, value)

How to save the given value into the given Redis key. Subclasses have to implement it. By default it raises NotImplementedError.

Parameters:
  • session (sider.session.Session) – the session object going to store the given keyvalue pair
  • key (str) – the key name to save the value
  • value – the value to save into the key
Returns:

the Python representation of the saved value. it is equivalent to the given value but may not equal nor the same to

Previous topic

sider.session — Sessions

Next topic

sider.hash — Hash objects

This Page