Add Tuple column type

PYTHON-306
This commit is contained in:
Adam Holmberg
2016-02-11 10:01:55 -06:00
parent 7379472cf1
commit be3a0de506
3 changed files with 70 additions and 6 deletions

View File

@@ -796,6 +796,65 @@ class UDTValueManager(BaseValueManager):
self.previous_value = copy(self.value)
class Tuple(Column):
"""
Stores a fixed-length set of positional values
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/tupleType.html
"""
def __init__(self, *args, **kwargs):
"""
:param args: column types representing tuple composition
"""
self.db_type = 'tuple<{0}>'.format(', '.join(typ.db_type for typ in args))
if not args:
raise ValueError("Tuple must specify at least one inner type")
sub_types = []
for arg in args:
inheritance_comparator = issubclass if isinstance(arg, type) else isinstance
if not inheritance_comparator(arg, Column):
raise ValidationError("%s is not a column class" % (arg,))
if arg.db_type is None:
raise ValidationError("%s is an abstract type" % (arg,))
sub_types.append(arg() if isinstance(arg, type) else arg)
self.sub_types = sub_types
super(Tuple, self).__init__(**kwargs)
def validate(self, value):
val = super(Tuple, self).validate(value)
if val is None:
return
if len(val) > self.sub_types:
raise ValidationError("Value %r has more fields than tuple definition (%s)" %
(val, ', '.join(t for t in self.sub_types)))
return tuple(t.validate(v) for t, v in zip(self.sub_types, val))
def to_python(self, value):
if value is None:
return tuple()
return tuple(t.to_python(v) for t, v in zip(self.sub_types, value))
def to_database(self, value):
if value is None:
return
return tuple(t.to_database(v) for t, v in zip(self.sub_types, value))
@property
def sub_columns(self):
return self.sub_types
# TODO:
# sub_columns --> sub_types
# test UDTs in tuples, vice versa
# refactor init validation to common base
# cqlsh None in tuple should display as null
class UserDefinedType(Column):
"""
User Defined Type column

View File

@@ -56,9 +56,8 @@ def default():
cluster = Cluster()
session = cluster.connect()
session.row_factory = dict_factory
_register_known_types(cluster)
_setup_session(session)
log.debug("cqlengine connection initialized with default session to localhost")
@@ -85,7 +84,7 @@ def set_session(s):
if not models.DEFAULT_KEYSPACE and session.keyspace:
models.DEFAULT_KEYSPACE = session.keyspace
_register_known_types(cluster)
_setup_session(session)
log.debug("cqlengine connection initialized with %s", s)
@@ -138,9 +137,15 @@ def setup(
raise
if consistency is not None:
session.default_consistency_level = consistency
session.row_factory = dict_factory
_register_known_types(cluster)
_setup_session(session)
def _setup_session(session):
session.row_factory = dict_factory
enc = session.encoder
enc.mapping[tuple] = enc.cql_encode_tuple
_register_known_types(session.cluster)
def execute(query, params=None, consistency_level=None, timeout=NOT_SET):

View File

@@ -84,7 +84,7 @@ class Encoder(object):
OrderedMap: self.cql_encode_map_collection,
OrderedMapSerializedKey: self.cql_encode_map_collection,
list: self.cql_encode_list_collection,
tuple: self.cql_encode_list_collection,
tuple: self.cql_encode_list_collection, # TODO: change to tuple in next major
set: self.cql_encode_set_collection,
sortedset: self.cql_encode_set_collection,
frozenset: self.cql_encode_set_collection,