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
.
-
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()
anddecode()
methods in subclasses.-
decode
(bulk)¶ Decodes a Redis
bulk
to Python object. Every subclass ofBulk
must implement this method. By default it raisesNotImplementedError
.Parameters: bulk ( str
) – a Redis bullk to decode into Python objectReturns: a decoded Python object
-
encode
(value)¶ Encodes a Python
value
into Redis bulk. Every subclass ofBulk
must implement this method. By default it raisesNotImplementedError
.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'
-
bytes_type
¶ alias of
str
-
-
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
) Thestrftime()
format string for RFC 3339.
-
-
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.-
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 oftzinfo
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 stringReturns: 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 othercollections.Mapping
objects.Parameters:
-
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 othercollections.Sequence
objects except strings. (UseByteString
orUnicodeString
for strings.)Parameters: value_type ( Bulk
,type
) – the type of values the list will contain. default isString
-
class
sider.types.
Set
(value_type=None)¶ Bases:
sider.types.Value
The type object for
sider.set.Set
objects and othercollections.Set
objects.Parameters: value_type ( Bulk
,type
) – the type of values the set will contain. default isString
-
class
sider.types.
SortedSet
(value_type=None)¶ Bases:
sider.types.Set
The type object for
sider.sortedset.SortedSet
objects.Parameters: value_type ( Bulk
,type
) – the type of values the sorted set will contain. default isString
-
sider.types.
String
¶ alias of
ByteString
-
class
sider.types.
TZDateTime
¶ Bases:
sider.types.DateTime
Similar to
DateTime
except it accepts only tz-awaredatetime.datetime
values. All values are internally stored inUTC
.>>> 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 raiseValueError
.
-
class
sider.types.
TZTime
¶ Bases:
sider.types.Time
Similar to
Time
except it accepts only tz-awaredatetime.time
values.>>> from sider.datetime import FixedOffset >>> time = datetime.time(18, 21, 34, 638972, ... tzinfo=FixedOffset(540)) >>> tztime = TZTime() >>> tztime.encode(time) '18:21:34.638972+09:00' >>> tztime.decode(_) datetime.time(18, 21, 34, 638972, tzinfo=sider.datetime.FixedOffset(540)) >>> utctime = datetime.time(9, 21, 34, 638972, tzinfo=UTC) >>> tztime.encode(utctime) '09:21:34.638972Z' >>> tztime.decode(_) datetime.time(9, 21, 34, 638972, tzinfo=sider.datetime.Utc())
If any naive
datetime.time
has passed it will raiseValueError
.
-
class
sider.types.
Time
¶ Bases:
sider.types.Bulk
Stores naive
datetime.time
values.>>> time = Time() >>> time.decode('09:21:34.638972') datetime.time(9, 21, 34, 638972) >>> time.encode(_) '09:21:34.638972'
It doesn’t store
tzinfo
data.>>> from sider.datetime import UTC >>> time = Time() >>> decoded = time.decode('09:21:34.638972Z') >>> decoded datetime.time(9, 21, 34, 638972) >>> time.encode(decoded.replace(tzinfo=UTC)) '09:21:34.638972'
Note
If you must be aware of time zone, use
TZTime
instead.-
parse_time
(bulk, drop_tzinfo)¶ Parses an encoded
datetime.time
.Parameters: bulk ( basestring
) – an encoded timeReturns: a parsed time Return type: datetime.time
Note
It is for internal use and
decode()
method actually uses this method.
-
-
class
sider.types.
TimeDelta
¶ Bases:
sider.types.Bulk
Stores
datetime.timedelta
values.>>> import datetime >>> td = TimeDelta() >>> delta = datetime.timedelta(days=3, seconds=53, microseconds=123123) >>> td.encode(delta) '3,53,123123' >>> td.decode(_) datetime.timedelta(3, 53, 123123)
-
class
sider.types.
Tuple
(*field_types)¶ Bases:
sider.types.Bulk
Stores tuples of fixed fields. It can be used for compositing multiple fields into one field in ad-hoc way. For example, if you want to store 3D point value without defining new
Type
:Tuple(Integer, Integer, Integer)
The above type will store three integers in a field.
>>> int_str_int = Tuple(Integer, ByteString, Integer) >>> int_str_int.encode((123, 'abc\ndef', 456)) '3,7,3\n123\nabc\ndef\n456' >>> int_str_int.decode(_) (123, 'abc\ndef', 456)
Encoded values become a bulk bytes. It consists of a header line and other lines that contain field values. The first header line is a comma-separated integers that represent each byte size of encoded field values.
tuple ::=
header
(newline field)* header ::= [size
(","size
)*] size ::= digit+ digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"Parameters: *field_types – the variable number of field types -
field_types
= None¶ (
tuple
) The tuple of field types.
-
-
class
sider.types.
UUID
¶ Bases:
sider.types.Bulk
Stores
uuid.UUID
values. For example:>>> import uuid >>> u = UUID() >>> u.encode(uuid.UUID(int=134626331218489933988508161913704617318)) '65481698-2f85-4bd6-8f7c-ee8aaecf1566' >>> u.decode('65481698-2f85-4bd6-8f7c-ee8aaecf1566') UUID('65481698-2f85-4bd6-8f7c-ee8aaecf1566')
-
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'
-
string_type
¶ alias of
unicode
-
-
class
sider.types.
Value
¶ Bases:
object
There are two layers behind Sider types: the lower one is this
Value
and the higher one isBulk
.Value
types can be set to Redis keys, but unlikeBulk
it cannot be a value type of other richValue
types e.g.List
,Hash
.In most cases you (users) don’t have to subclass
Value
, and should not. Direct subclasses ofValue
aren’t about encodings/decodings of Python object but simply Python-side representations of Redis types. It actually doesn’t have methods likeencode()
anddecode()
. These methods appear underBulk
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
implementsave_value()
andload_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 givenvalue_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- value_type (
-
load_value
(session, key)¶ How to load the value from the given Redis
key
. Subclasses have to implement it. By default it raisesNotImplementedError
.Parameters: - session (
sider.session.Session
) – the session object that stores the givenkey
- key (
str
) – the key name to load
Returns: the Python representation of the loaded value
- session (
-
save_value
(session, key, value)¶ How to save the given
value
into the given Rediskey
. Subclasses have to implement it. By default it raisesNotImplementedError
.Parameters: - session (
sider.session.Session
) – the session object going to store the givenkey
–value
pair - key (
str
) – the key name to save thevalue
- 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- session (
-
classmethod