From aee5b28d62246a7a70f46aea5a359ec3c2428ea6 Mon Sep 17 00:00:00 2001 From: yi719 Date: Thu, 10 Sep 2015 16:09:08 +0800 Subject: [PATCH 01/25] Fix UnicodeDecodeError of UserType --- cassandra/cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/cluster.py b/cassandra/cluster.py index 029ccfac66..a8aae84ffe 100644 --- a/cassandra/cluster.py +++ b/cassandra/cluster.py @@ -1955,7 +1955,7 @@ def user_type_registered(self, keyspace, user_type, klass): def encode(val): return '{ %s }' % ' , '.join('%s : %s' % ( - field_name, + field_name.encode('utf-8'), self.encoder.cql_encode_all_types(getattr(val, field_name, None)) ) for field_name in type_meta.field_names) From 0c808fb8b5c8fa40e76db588df4732143093f386 Mon Sep 17 00:00:00 2001 From: yi719 Date: Tue, 15 Sep 2015 14:44:54 +0800 Subject: [PATCH 02/25] Make sure UDT field name are encoded UTF-8 --- cassandra/cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/cluster.py b/cassandra/cluster.py index a8aae84ffe..be8a5702ec 100644 --- a/cassandra/cluster.py +++ b/cassandra/cluster.py @@ -1955,7 +1955,7 @@ def user_type_registered(self, keyspace, user_type, klass): def encode(val): return '{ %s }' % ' , '.join('%s : %s' % ( - field_name.encode('utf-8'), + field_name.encode('utf-8') if six.PY2 and isinstance(field_name, six.text_type) else field_name, self.encoder.cql_encode_all_types(getattr(val, field_name, None)) ) for field_name in type_meta.field_names) From 8bced71679778de02fd011687de737c243040ac4 Mon Sep 17 00:00:00 2001 From: yi719 Date: Mon, 28 Sep 2015 16:29:00 +0800 Subject: [PATCH 03/25] Deal with default --- cassandra/cqlengine/columns.py | 52 ++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index 11481bcd81..d77e00d8ab 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -18,6 +18,8 @@ import six import warnings +import msgpack + from cassandra import util from cassandra.cqltypes import DateType, SimpleDateType from cassandra.cqlengine import ValidationError @@ -195,6 +197,8 @@ def to_python(self, value): Converts data from the database into python values raises a ValidationError if the value can't be converted """ + if value is None and self.has_default: + return self.get_default() return value def to_database(self, value): @@ -313,7 +317,7 @@ def __init__(self, min_length=None, max_length=None, **kwargs): """ :param int min_length: Sets the minimum length of this string, for validation purposes. Defaults to 1 if this is a ``required`` column. Otherwise, None. - :param int max_length: Sets the maximum length of this string, for validation purposes. + :param int max_lemgth: Sets the maximum length of this string, for validation purposes. """ self.min_length = min_length or (1 if kwargs.get('required', False) else None) self.max_length = max_length @@ -333,6 +337,11 @@ def validate(self, value): raise ValidationError('{0} is shorter than {1} characters'.format(self.column_name, self.min_length)) return value + def to_python(self, value): + value = self.validate(value) + if value is None and self.has_default: + return self.get_default() + return value class Integer(Column): """ @@ -351,7 +360,10 @@ def validate(self, value): raise ValidationError("{0} {1} can't be converted to integral value".format(self.column_name, value)) def to_python(self, value): - return self.validate(value) + value = self.validate(value) + if value is None and self.has_default: + return self.get_default() + return value def to_database(self, value): return self.validate(value) @@ -897,3 +909,39 @@ def to_database(self, value): def get_cql(self): return "token({0})".format(", ".join(c.cql for c in self.partition_columns)) + + +def decode_datetime(obj): + if b'__datetime__' in obj: + obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f") + return obj + + +def encode_datetime(obj): + if isinstance(obj, datetime.datetime): + return {'__datetime__': True, 'as_str': obj.strftime("%Y%m%dT%H:%M:%S.%f")} + return obj + + +class Json(Blob): + def to_database(self, value): + if not value: + return None + value = Column.to_database(self, value) + ret = msgpack.packb(value, use_bin_type=True, default=encode_datetime) + return bytearray(ret) + + def to_python(self, value): + if not value: + return {} + return msgpack.unpackb(value, object_hook=decode_datetime, encoding='utf-8') + + +def to_python(self, value): + ret = {} + for k, v in value.items(): + ret[k] = self.user_type._fields[k].to_python(v) + return self.user_type(**ret) + + +UserDefinedType.to_python = to_python From 2053041d6831701fe9af484810704519dcac27a9 Mon Sep 17 00:00:00 2001 From: yi719 Date: Mon, 28 Sep 2015 16:29:47 +0800 Subject: [PATCH 04/25] deal with encode error of udt --- cassandra/cqlengine/usertype.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cassandra/cqlengine/usertype.py b/cassandra/cqlengine/usertype.py index 88ec033ba8..c5ca16d2ec 100644 --- a/cassandra/cqlengine/usertype.py +++ b/cassandra/cqlengine/usertype.py @@ -27,7 +27,6 @@ class BaseUserType(object): def __init__(self, **values): self._values = {} - for name, field in self._fields.items(): value = values.get(name, None) if value is not None or isinstance(field, columns.BaseContainerColumn): @@ -56,7 +55,13 @@ def __ne__(self, other): return not self.__eq__(other) def __str__(self): - return "{{{0}}}".format(', '.join("'{0}': {1}".format(k, getattr(self, k)) for k, v in six.iteritems(self._values))) + lst = [] + for k, v in six.iteritems(self._values): + val = getattr(self, k) + if six.PY2 and isinstance(val, six.text_type): + val = val.encode('utf-8') + lst.append("'{0}': {1}".format(k, val)) + return "{{{0}}}".format(', '.join(lst)) def has_changed_fields(self): return any(v.changed for v in self._values.values()) @@ -145,7 +150,7 @@ class UserTypeMetaClass(type): def __new__(cls, name, bases, attrs): field_dict = OrderedDict() - field_defs = [(k, v) for k, v in attrs.items() if isinstance(v, columns.Column)] + field_defs = [(k.decode('utf-8'), v) for k, v in attrs.items() if isinstance(v, columns.Column)] field_defs = sorted(field_defs, key=lambda x: x[1].position) def _transform_column(field_name, field_obj): From be6f1a6388a11313be1b8c0361e071193901f5d6 Mon Sep 17 00:00:00 2001 From: yi719 Date: Mon, 28 Sep 2015 16:34:16 +0800 Subject: [PATCH 05/25] Typo --- cassandra/cqlengine/columns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index d77e00d8ab..b2b2691442 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -317,7 +317,7 @@ def __init__(self, min_length=None, max_length=None, **kwargs): """ :param int min_length: Sets the minimum length of this string, for validation purposes. Defaults to 1 if this is a ``required`` column. Otherwise, None. - :param int max_lemgth: Sets the maximum length of this string, for validation purposes. + :param int max_length: Sets the maximum length of this string, for validation purposes. """ self.min_length = min_length or (1 if kwargs.get('required', False) else None) self.max_length = max_length From cf7809f044a40b69b81c987245c7637c8eb2541c Mon Sep 17 00:00:00 2001 From: yi719 Date: Mon, 28 Sep 2015 17:25:01 +0800 Subject: [PATCH 06/25] Deal with udt is None --- cassandra/cqlengine/columns.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index b2b2691442..f8c61f5d59 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -939,8 +939,9 @@ def to_python(self, value): def to_python(self, value): ret = {} - for k, v in value.items(): - ret[k] = self.user_type._fields[k].to_python(v) + for col_name, col in self.user_type._fields.items(): + val = value.get(col_name) if value is not None else None + ret[col_name] = col.to_python(val) return self.user_type(**ret) From 89fe24dd630a64de0f86e8323b02289a5bf55409 Mon Sep 17 00:00:00 2001 From: yi719 Date: Sat, 3 Oct 2015 09:39:39 +0800 Subject: [PATCH 07/25] Add support for default value of Json field --- cassandra/cqlengine/columns.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index f8c61f5d59..719830718e 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -932,8 +932,9 @@ def to_database(self, value): return bytearray(ret) def to_python(self, value): - if not value: - return {} + if value is None and self.has_default: + return self.get_default() + return msgpack.unpackb(value, object_hook=decode_datetime, encoding='utf-8') From 2bfa294e70f36f072bf02638cceb9570d480c1e3 Mon Sep 17 00:00:00 2001 From: yi719 Date: Sat, 3 Oct 2015 21:25:34 +0800 Subject: [PATCH 08/25] Fix datetime when user msgpack --- cassandra/cqlengine/columns.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index 719830718e..f05954fa28 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -913,12 +913,12 @@ def get_cql(self): def decode_datetime(obj): if b'__datetime__' in obj: - obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f") + obj = datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f") return obj def encode_datetime(obj): - if isinstance(obj, datetime.datetime): + if isinstance(obj, datetime): return {'__datetime__': True, 'as_str': obj.strftime("%Y%m%dT%H:%M:%S.%f")} return obj From 7850a952217c898d510b9f9fc6ea326d95666c2b Mon Sep 17 00:00:00 2001 From: yi719 Date: Thu, 8 Oct 2015 16:03:32 +0800 Subject: [PATCH 09/25] Fix timeout in geventreactor --- cassandra/io/geventreactor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cassandra/io/geventreactor.py b/cassandra/io/geventreactor.py index f26e61523c..a063df1b70 100644 --- a/cassandra/io/geventreactor.py +++ b/cassandra/io/geventreactor.py @@ -36,7 +36,8 @@ def is_timeout(err): return ( err in (EINPROGRESS, EALREADY, EWOULDBLOCK) or - (err == EINVAL and os.name in ('nt', 'ce')) + (err == EINVAL and os.name in ('nt', 'ce')) or + isinstance(err, socket.timeout) ) From b98c4c7b19b0dda37b8467eaafdb6260aa3f4fd1 Mon Sep 17 00:00:00 2001 From: yi719 Date: Sat, 10 Oct 2015 11:45:18 +0800 Subject: [PATCH 10/25] Fix PYTHON-344 see https://datastax-oss.atlassian.net/browse/PYTHON-344 --- cassandra/cqlengine/columns.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index f05954fa28..338ef3731a 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -847,10 +847,11 @@ def sub_columns(self): class UDTValueManager(BaseValueManager): @property def changed(self): - return self.value != self.previous_value or self.value.has_changed_fields() + return self.value != self.previous_value or (self.value is not None and self.value.has_changed_fields()) def reset_previous_value(self): - self.value.reset_changed_fields() + if self.value is not None: + self.value.reset_changed_fields() self.previous_value = copy(self.value) From ab5dd9a6d035b445311d6fece74bf5b5a11720f5 Mon Sep 17 00:00:00 2001 From: yi719 Date: Sat, 10 Oct 2015 11:46:43 +0800 Subject: [PATCH 11/25] Do not use default value in to_database for UserDefinedType --- cassandra/cqlengine/columns.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index 338ef3731a..dd159ab801 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -880,6 +880,9 @@ def __init__(self, user_type, **kwargs): def sub_columns(self): return list(self.user_type._fields.values()) + def to_database(self, value): + return value + def resolve_udts(col_def, out_list): for col in col_def.sub_columns: From f31de5caa0e1fea4ccb0a46e15164cd027989fb5 Mon Sep 17 00:00:00 2001 From: yi719 Date: Mon, 2 Nov 2015 16:03:07 +0800 Subject: [PATCH 12/25] Fix to_python error of JsonColum --- cassandra/cqlengine/columns.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index dd159ab801..e67a0f38e8 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -938,7 +938,8 @@ def to_database(self, value): def to_python(self, value): if value is None and self.has_default: return self.get_default() - + if not isinstance(value, (six.binary_type, bytearray)): + return value return msgpack.unpackb(value, object_hook=decode_datetime, encoding='utf-8') From 797e6def439ebf219f2fc750b99596d0aea18e52 Mon Sep 17 00:00:00 2001 From: yi719 Date: Sun, 15 Nov 2015 18:32:35 +0800 Subject: [PATCH 13/25] Fix attribute name bug in usertype --- cassandra/cqlengine/usertype.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/cqlengine/usertype.py b/cassandra/cqlengine/usertype.py index c5ca16d2ec..c3e2539ca1 100644 --- a/cassandra/cqlengine/usertype.py +++ b/cassandra/cqlengine/usertype.py @@ -92,7 +92,7 @@ def __len__(self): try: return self._len except: - self._len = len(self._columns.keys()) + self._len = len(self._fields.keys()) return self._len def keys(self): From d03a51b609b4873d4f167913776fb01a2ed4273b Mon Sep 17 00:00:00 2001 From: yi719 Date: Sun, 15 Nov 2015 18:35:34 +0800 Subject: [PATCH 14/25] Make to_database is called on sub_columns of userdefinedtype --- cassandra/cqlengine/columns.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index e67a0f38e8..55920e3969 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -881,6 +881,8 @@ def sub_columns(self): return list(self.user_type._fields.values()) def to_database(self, value): + for col_name, col in self.user_type._fields.items(): + value[col_name] = col.to_database(value[col_name]) return value From e8feccd120e8ff49f8a7607037d3d05d2a391991 Mon Sep 17 00:00:00 2001 From: yi719 Date: Mon, 23 Nov 2015 12:09:39 +0800 Subject: [PATCH 15/25] Fix value missing in userdefinedtype's to_database --- cassandra/cqlengine/columns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index 55920e3969..fe56c8871e 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -882,7 +882,7 @@ def sub_columns(self): def to_database(self, value): for col_name, col in self.user_type._fields.items(): - value[col_name] = col.to_database(value[col_name]) + value[col_name] = col.to_database(getattr(value, col_name, None)) return value From 562f5c6b58154813957431cd08fcb767400ca1a6 Mon Sep 17 00:00:00 2001 From: yi719 Date: Mon, 23 Nov 2015 16:02:03 +0800 Subject: [PATCH 16/25] Fix userdefinedtype's to_database --- cassandra/cqlengine/columns.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index fe56c8871e..7234d34dfb 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -881,8 +881,9 @@ def sub_columns(self): return list(self.user_type._fields.values()) def to_database(self, value): - for col_name, col in self.user_type._fields.items(): - value[col_name] = col.to_database(getattr(value, col_name, None)) + for k, v in value.items(): + col = self.user_type._fields[k] + value[k] = col.to_database(v) return value From 5b0c75da92fb976ef2842923760f8809f10f1689 Mon Sep 17 00:00:00 2001 From: yi719 Date: Wed, 6 Jan 2016 11:54:00 +0800 Subject: [PATCH 17/25] Fix bug in UserDefinedType's to_database --- cassandra/cqlengine/columns.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index 7234d34dfb..815540a8cf 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -881,10 +881,11 @@ def sub_columns(self): return list(self.user_type._fields.values()) def to_database(self, value): - for k, v in value.items(): + ret = deepcopy(value) + for k, v in ret.items(): col = self.user_type._fields[k] - value[k] = col.to_database(v) - return value + ret[k] = col.to_database(v) + return ret def resolve_udts(col_def, out_list): From e554e52eaeb340c09f2da8b64435e85fbf105eb2 Mon Sep 17 00:00:00 2001 From: yi719 Date: Fri, 19 Feb 2016 14:24:22 +0800 Subject: [PATCH 18/25] Fix default value for model --- cassandra/cqlengine/models.py | 4 +--- cassandra/cqlengine/usertype.py | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cassandra/cqlengine/models.py b/cassandra/cqlengine/models.py index ddb7945995..f3e00d8305 100644 --- a/cassandra/cqlengine/models.py +++ b/cassandra/cqlengine/models.py @@ -361,11 +361,9 @@ def __init__(self, **values): self._ttl = self.__default_ttl__ self._timestamp = None self._transaction = None - for name, column in self._columns.items(): value = values.get(name, None) - if value is not None or isinstance(column, columns.BaseContainerColumn): - value = column.to_python(value) + value = column.to_python(value) value_mngr = column.value_manager(self, column, value) if name in values: value_mngr.explicit = True diff --git a/cassandra/cqlengine/usertype.py b/cassandra/cqlengine/usertype.py index c3e2539ca1..6c98bd4bed 100644 --- a/cassandra/cqlengine/usertype.py +++ b/cassandra/cqlengine/usertype.py @@ -29,8 +29,7 @@ def __init__(self, **values): self._values = {} for name, field in self._fields.items(): value = values.get(name, None) - if value is not None or isinstance(field, columns.BaseContainerColumn): - value = field.to_python(value) + value = field.to_python(value) value_mngr = field.value_manager(self, field, value) if name in values: value_mngr.explicit = True From 9ba7881bf6a98b25954f9eff0f1d15afbed0b4ec Mon Sep 17 00:00:00 2001 From: yi719 Date: Fri, 26 Feb 2016 18:01:03 +0800 Subject: [PATCH 19/25] check in_buffer_size when socket.error --- cassandra/io/geventreactor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/io/geventreactor.py b/cassandra/io/geventreactor.py index a063df1b70..0340a0c4d6 100644 --- a/cassandra/io/geventreactor.py +++ b/cassandra/io/geventreactor.py @@ -153,7 +153,7 @@ def handle_read(self): if len(buf) < self.in_buffer_size: break except socket.error as err: - if not is_timeout(err): + if not is_timeout(err) and len(buf) != self.in_buffer_size: log.debug("Exception during socket recv for %s: %s", self, err) self.defunct(err) return # leave the read loop From b1a9321a74c24cda91520f61514d09f2348c1b9b Mon Sep 17 00:00:00 2001 From: yi719 Date: Fri, 26 Feb 2016 18:04:08 +0800 Subject: [PATCH 20/25] Fix timeout for model --- cassandra/cqlengine/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/cqlengine/models.py b/cassandra/cqlengine/models.py index f3e00d8305..8543883068 100644 --- a/cassandra/cqlengine/models.py +++ b/cassandra/cqlengine/models.py @@ -373,7 +373,7 @@ def __init__(self, **values): # that update should be used when persisting changes self._is_persisted = False self._batch = None - self._timeout = connection.NOT_SET + self._timeout = 2 def __repr__(self): return '{0}({1})'.format(self.__class__.__name__, From 5bafa96a21aba0cf69b11b9a4893985460eaa53e Mon Sep 17 00:00:00 2001 From: yi719 Date: Fri, 26 Feb 2016 18:24:05 +0800 Subject: [PATCH 21/25] Revert "Fix timeout for model" This reverts commit b1a9321a74c24cda91520f61514d09f2348c1b9b. --- cassandra/cqlengine/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/cqlengine/models.py b/cassandra/cqlengine/models.py index 8543883068..f3e00d8305 100644 --- a/cassandra/cqlengine/models.py +++ b/cassandra/cqlengine/models.py @@ -373,7 +373,7 @@ def __init__(self, **values): # that update should be used when persisting changes self._is_persisted = False self._batch = None - self._timeout = 2 + self._timeout = connection.NOT_SET def __repr__(self): return '{0}({1})'.format(self.__class__.__name__, From c11a4c84edccd4c05b836498e63664c49c30f665 Mon Sep 17 00:00:00 2001 From: ofshellohicy Date: Fri, 26 Feb 2016 18:29:52 +0800 Subject: [PATCH 22/25] fix BaseModel unpickle error --- cassandra/cqlengine/models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cassandra/cqlengine/models.py b/cassandra/cqlengine/models.py index f3e00d8305..2ed75b06f1 100644 --- a/cassandra/cqlengine/models.py +++ b/cassandra/cqlengine/models.py @@ -388,6 +388,12 @@ def __str__(self): return '{0} <{1}>'.format(self.__class__.__name__, ', '.join('{0}={1}'.format(k, getattr(self, k)) for k in self._primary_keys.keys())) + def __setstate__(self, state): + # register when unpickle from cache, avoid property missing + state._timeout = connection.NOT_SET + state.update(self.__dict__) # pylint: disable=E0203 + self.__dict__ = state + @classmethod def _discover_polymorphic_submodels(cls): if not cls._is_polymorphic_base: From 8a37411befa3499b617405ae92701332305ddc15 Mon Sep 17 00:00:00 2001 From: ofshellohicy Date: Sat, 27 Feb 2016 11:14:02 +0800 Subject: [PATCH 23/25] fix set state for BaseModel --- cassandra/cqlengine/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cassandra/cqlengine/models.py b/cassandra/cqlengine/models.py index 2ed75b06f1..d14a6bdf74 100644 --- a/cassandra/cqlengine/models.py +++ b/cassandra/cqlengine/models.py @@ -390,9 +390,9 @@ def __str__(self): def __setstate__(self, state): # register when unpickle from cache, avoid property missing - state._timeout = connection.NOT_SET state.update(self.__dict__) # pylint: disable=E0203 self.__dict__ = state + self._timeout = connection.NOT_SET @classmethod def _discover_polymorphic_submodels(cls): From dd9c32048a2cf98f881cb20270373b3387dc9a08 Mon Sep 17 00:00:00 2001 From: _v7__ Date: Fri, 4 Mar 2016 14:27:28 +0800 Subject: [PATCH 24/25] fix get column default value --- cassandra/cqlengine/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cassandra/cqlengine/models.py b/cassandra/cqlengine/models.py index d14a6bdf74..7732fd3384 100644 --- a/cassandra/cqlengine/models.py +++ b/cassandra/cqlengine/models.py @@ -259,6 +259,8 @@ def __get__(self, instance, owner): """ try: return instance._values[self.column.column_name].getval() + except KeyError: + return self.column.get_default() except AttributeError: return self.query_evaluator From 93cdc3f9b95a98f172f3d9159445c97b27789554 Mon Sep 17 00:00:00 2001 From: _v7__ Date: Fri, 4 Mar 2016 15:37:52 +0800 Subject: [PATCH 25/25] fix set column value --- cassandra/cqlengine/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cassandra/cqlengine/models.py b/cassandra/cqlengine/models.py index 7732fd3384..f9e5ae5807 100644 --- a/cassandra/cqlengine/models.py +++ b/cassandra/cqlengine/models.py @@ -270,6 +270,8 @@ def __set__(self, instance, value): TODO: use None instance to create update statements """ if instance: + if instance._values.get(self.column.column_name, None) is None: + instance._values[self.column.column_name] = self.column.value_manager(instance, self.column, value) return instance._values[self.column.column_name].setval(value) else: raise AttributeError('cannot reassign column values')