fixed #67 (validation on keyname typos) #66 (removed defaults on columns) and #57 and removed autoid
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
0.4.0
|
||||||
|
* removed default values from all column types
|
||||||
|
* explicit primary key is required (automatic id removed)
|
||||||
|
|
||||||
0.3.3
|
0.3.3
|
||||||
* added abstract base class models
|
* added abstract base class models
|
||||||
|
|
||||||
|
|||||||
@@ -236,9 +236,6 @@ class Integer(Column):
|
|||||||
class DateTime(Column):
|
class DateTime(Column):
|
||||||
db_type = 'timestamp'
|
db_type = 'timestamp'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
super(DateTime, self).__init__(**kwargs)
|
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if isinstance(value, datetime):
|
if isinstance(value, datetime):
|
||||||
return value
|
return value
|
||||||
@@ -265,8 +262,6 @@ class DateTime(Column):
|
|||||||
class Date(Column):
|
class Date(Column):
|
||||||
db_type = 'timestamp'
|
db_type = 'timestamp'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
super(Date, self).__init__(**kwargs)
|
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
if isinstance(value, datetime):
|
if isinstance(value, datetime):
|
||||||
@@ -294,9 +289,6 @@ class UUID(Column):
|
|||||||
|
|
||||||
re_uuid = re.compile(r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
re_uuid = re.compile(r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
||||||
|
|
||||||
def __init__(self, default=lambda:uuid4(), **kwargs):
|
|
||||||
super(UUID, self).__init__(default=default, **kwargs)
|
|
||||||
|
|
||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
val = super(UUID, self).validate(value)
|
val = super(UUID, self).validate(value)
|
||||||
if val is None: return
|
if val is None: return
|
||||||
@@ -319,10 +311,6 @@ class TimeUUID(UUID):
|
|||||||
|
|
||||||
db_type = 'timeuuid'
|
db_type = 'timeuuid'
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
kwargs.setdefault('default', lambda: uuid1())
|
|
||||||
super(TimeUUID, self).__init__(**kwargs)
|
|
||||||
|
|
||||||
class Boolean(Column):
|
class Boolean(Column):
|
||||||
db_type = 'boolean'
|
db_type = 'boolean'
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from collections import OrderedDict
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from cqlengine import columns
|
from cqlengine import columns
|
||||||
from cqlengine.exceptions import ModelException, CQLEngineException
|
from cqlengine.exceptions import ModelException, CQLEngineException, ValidationError
|
||||||
from cqlengine.query import QuerySet, DMLQuery
|
from cqlengine.query import QuerySet, DMLQuery
|
||||||
from cqlengine.query import DoesNotExist as _DoesNotExist
|
from cqlengine.query import DoesNotExist as _DoesNotExist
|
||||||
from cqlengine.query import MultipleObjectsReturned as _MultipleObjectsReturned
|
from cqlengine.query import MultipleObjectsReturned as _MultipleObjectsReturned
|
||||||
@@ -66,6 +66,11 @@ class BaseModel(object):
|
|||||||
|
|
||||||
def __init__(self, **values):
|
def __init__(self, **values):
|
||||||
self._values = {}
|
self._values = {}
|
||||||
|
|
||||||
|
extra_columns = set(values.keys()) - set(self._columns.keys())
|
||||||
|
if extra_columns:
|
||||||
|
raise ValidationError("Incorrect columns passed: {}".format(extra_columns))
|
||||||
|
|
||||||
for name, column in self._columns.items():
|
for name, column in self._columns.items():
|
||||||
value = values.get(name, None)
|
value = values.get(name, None)
|
||||||
if value is not None: value = column.to_python(value)
|
if value is not None: value = column.to_python(value)
|
||||||
@@ -226,8 +231,7 @@ class ModelMetaClass(type):
|
|||||||
|
|
||||||
#prepend primary key if one hasn't been defined
|
#prepend primary key if one hasn't been defined
|
||||||
if not is_abstract and not any([v.primary_key for k,v in column_definitions]):
|
if not is_abstract and not any([v.primary_key for k,v in column_definitions]):
|
||||||
k,v = 'id', columns.UUID(primary_key=True)
|
raise ModelDefinitionException("At least 1 primary key is required.")
|
||||||
column_definitions = [(k,v)] + column_definitions
|
|
||||||
|
|
||||||
has_partition_keys = any(v.partition_key for (k, v) in column_definitions)
|
has_partition_keys = any(v.partition_key for (k, v) in column_definitions)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from datetime import datetime, timedelta
|
|||||||
from datetime import date
|
from datetime import date
|
||||||
from datetime import tzinfo
|
from datetime import tzinfo
|
||||||
from decimal import Decimal as D
|
from decimal import Decimal as D
|
||||||
|
from uuid import uuid4, uuid1
|
||||||
from cqlengine import ValidationError
|
from cqlengine import ValidationError
|
||||||
|
|
||||||
from cqlengine.tests.base import BaseCassEngTestCase
|
from cqlengine.tests.base import BaseCassEngTestCase
|
||||||
@@ -119,7 +120,7 @@ class TestDecimal(BaseCassEngTestCase):
|
|||||||
class TestTimeUUID(BaseCassEngTestCase):
|
class TestTimeUUID(BaseCassEngTestCase):
|
||||||
class TimeUUIDTest(Model):
|
class TimeUUIDTest(Model):
|
||||||
test_id = Integer(primary_key=True)
|
test_id = Integer(primary_key=True)
|
||||||
timeuuid = TimeUUID()
|
timeuuid = TimeUUID(default=uuid1())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
@@ -132,6 +133,10 @@ class TestTimeUUID(BaseCassEngTestCase):
|
|||||||
delete_table(cls.TimeUUIDTest)
|
delete_table(cls.TimeUUIDTest)
|
||||||
|
|
||||||
def test_timeuuid_io(self):
|
def test_timeuuid_io(self):
|
||||||
|
"""
|
||||||
|
ensures that
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
t0 = self.TimeUUIDTest.create(test_id=0)
|
t0 = self.TimeUUIDTest.create(test_id=0)
|
||||||
t1 = self.TimeUUIDTest.get(test_id=0)
|
t1 = self.TimeUUIDTest.get(test_id=0)
|
||||||
|
|
||||||
@@ -139,8 +144,8 @@ class TestTimeUUID(BaseCassEngTestCase):
|
|||||||
|
|
||||||
class TestInteger(BaseCassEngTestCase):
|
class TestInteger(BaseCassEngTestCase):
|
||||||
class IntegerTest(Model):
|
class IntegerTest(Model):
|
||||||
test_id = UUID(primary_key=True)
|
test_id = UUID(primary_key=True, default=lambda:uuid4())
|
||||||
value = Integer(default=0)
|
value = Integer(default=0, required=True)
|
||||||
|
|
||||||
def test_default_zero_fields_validate(self):
|
def test_default_zero_fields_validate(self):
|
||||||
""" Tests that integer columns with a default value of 0 validate """
|
""" Tests that integer columns with a default value of 0 validate """
|
||||||
@@ -190,7 +195,13 @@ class TestText(BaseCassEngTestCase):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestExtraFieldsRaiseException(BaseCassEngTestCase):
|
||||||
|
class TestModel(Model):
|
||||||
|
id = UUID(primary_key=True, default=uuid4)
|
||||||
|
|
||||||
|
def test_extra_field(self):
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
self.TestModel.create(bacon=5000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
|
from uuid import uuid4
|
||||||
from cqlengine.query import QueryException
|
from cqlengine.query import QueryException
|
||||||
from cqlengine.tests.base import BaseCassEngTestCase
|
from cqlengine.tests.base import BaseCassEngTestCase
|
||||||
|
|
||||||
from cqlengine.exceptions import ModelException, CQLEngineException
|
from cqlengine.exceptions import ModelException, CQLEngineException
|
||||||
from cqlengine.models import Model
|
from cqlengine.models import Model, ModelDefinitionException
|
||||||
from cqlengine import columns
|
from cqlengine import columns
|
||||||
import cqlengine
|
import cqlengine
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
class TestModel(Model):
|
class TestModel(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
text = columns.Text()
|
text = columns.Text()
|
||||||
|
|
||||||
#check class attibutes
|
#check class attibutes
|
||||||
@@ -38,6 +40,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
-the db_map allows columns
|
-the db_map allows columns
|
||||||
"""
|
"""
|
||||||
class WildDBNames(Model):
|
class WildDBNames(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
content = columns.Text(db_field='words_and_whatnot')
|
content = columns.Text(db_field='words_and_whatnot')
|
||||||
numbers = columns.Integer(db_field='integers_etc')
|
numbers = columns.Integer(db_field='integers_etc')
|
||||||
|
|
||||||
@@ -61,17 +64,26 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
class Stuff(Model):
|
class Stuff(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
words = columns.Text()
|
words = columns.Text()
|
||||||
content = columns.Text()
|
content = columns.Text()
|
||||||
numbers = columns.Integer()
|
numbers = columns.Integer()
|
||||||
|
|
||||||
self.assertEquals(Stuff._columns.keys(), ['id', 'words', 'content', 'numbers'])
|
self.assertEquals(Stuff._columns.keys(), ['id', 'words', 'content', 'numbers'])
|
||||||
|
|
||||||
|
def test_exception_raised_when_creating_class_without_pk(self):
|
||||||
|
with self.assertRaises(ModelDefinitionException):
|
||||||
|
class TestModel(Model):
|
||||||
|
count = columns.Integer()
|
||||||
|
text = columns.Text(required=False)
|
||||||
|
|
||||||
|
|
||||||
def test_value_managers_are_keeping_model_instances_isolated(self):
|
def test_value_managers_are_keeping_model_instances_isolated(self):
|
||||||
"""
|
"""
|
||||||
Tests that instance value managers are isolated from other instances
|
Tests that instance value managers are isolated from other instances
|
||||||
"""
|
"""
|
||||||
class Stuff(Model):
|
class Stuff(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
num = columns.Integer()
|
num = columns.Integer()
|
||||||
|
|
||||||
inst1 = Stuff(num=5)
|
inst1 = Stuff(num=5)
|
||||||
@@ -86,6 +98,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
Tests that fields defined on the super class are inherited properly
|
Tests that fields defined on the super class are inherited properly
|
||||||
"""
|
"""
|
||||||
class TestModel(Model):
|
class TestModel(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
text = columns.Text()
|
text = columns.Text()
|
||||||
|
|
||||||
class InheritedModel(TestModel):
|
class InheritedModel(TestModel):
|
||||||
@@ -124,6 +137,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
Test compound partition key definition
|
Test compound partition key definition
|
||||||
"""
|
"""
|
||||||
class ModelWithPartitionKeys(cqlengine.Model):
|
class ModelWithPartitionKeys(cqlengine.Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
c1 = cqlengine.Text(primary_key=True)
|
c1 = cqlengine.Text(primary_key=True)
|
||||||
p1 = cqlengine.Text(partition_key=True)
|
p1 = cqlengine.Text(partition_key=True)
|
||||||
p2 = cqlengine.Text(partition_key=True)
|
p2 = cqlengine.Text(partition_key=True)
|
||||||
@@ -144,6 +158,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
def test_del_attribute_is_assigned_properly(self):
|
def test_del_attribute_is_assigned_properly(self):
|
||||||
""" Tests that columns that can be deleted have the del attribute """
|
""" Tests that columns that can be deleted have the del attribute """
|
||||||
class DelModel(Model):
|
class DelModel(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
key = columns.Integer(primary_key=True)
|
key = columns.Integer(primary_key=True)
|
||||||
data = columns.Integer(required=False)
|
data = columns.Integer(required=False)
|
||||||
|
|
||||||
@@ -156,9 +171,10 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
""" Tests that DoesNotExist exceptions are not the same exception between models """
|
""" Tests that DoesNotExist exceptions are not the same exception between models """
|
||||||
|
|
||||||
class Model1(Model):
|
class Model1(Model):
|
||||||
pass
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
|
|
||||||
class Model2(Model):
|
class Model2(Model):
|
||||||
pass
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
raise Model1.DoesNotExist
|
raise Model1.DoesNotExist
|
||||||
@@ -171,7 +187,8 @@ class TestModelClassFunction(BaseCassEngTestCase):
|
|||||||
def test_does_not_exist_inherits_from_superclass(self):
|
def test_does_not_exist_inherits_from_superclass(self):
|
||||||
""" Tests that a DoesNotExist exception can be caught by it's parent class DoesNotExist """
|
""" Tests that a DoesNotExist exception can be caught by it's parent class DoesNotExist """
|
||||||
class Model1(Model):
|
class Model1(Model):
|
||||||
pass
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
|
|
||||||
class Model2(Model1):
|
class Model2(Model1):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from unittest import skip
|
from unittest import skip
|
||||||
|
from uuid import uuid4
|
||||||
from cqlengine.tests.base import BaseCassEngTestCase
|
from cqlengine.tests.base import BaseCassEngTestCase
|
||||||
|
|
||||||
from cqlengine.management import create_table
|
from cqlengine.management import create_table
|
||||||
@@ -7,6 +8,7 @@ from cqlengine.models import Model
|
|||||||
from cqlengine import columns
|
from cqlengine import columns
|
||||||
|
|
||||||
class TestModel(Model):
|
class TestModel(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
count = columns.Integer()
|
count = columns.Integer()
|
||||||
text = columns.Text(required=False)
|
text = columns.Text(required=False)
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,18 @@ from cqlengine.models import Model
|
|||||||
from cqlengine import columns
|
from cqlengine import columns
|
||||||
|
|
||||||
class TestModel(Model):
|
class TestModel(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
count = columns.Integer()
|
count = columns.Integer()
|
||||||
text = columns.Text(required=False)
|
text = columns.Text(required=False)
|
||||||
a_bool = columns.Boolean(default=False)
|
a_bool = columns.Boolean(default=False)
|
||||||
|
|
||||||
|
class TestModel(Model):
|
||||||
|
id = columns.UUID(primary_key=True, default=lambda:uuid4())
|
||||||
|
count = columns.Integer()
|
||||||
|
text = columns.Text(required=False)
|
||||||
|
a_bool = columns.Boolean(default=False)
|
||||||
|
|
||||||
|
|
||||||
class TestModelIO(BaseCassEngTestCase):
|
class TestModelIO(BaseCassEngTestCase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -34,6 +42,8 @@ class TestModelIO(BaseCassEngTestCase):
|
|||||||
for cname in tm._columns.keys():
|
for cname in tm._columns.keys():
|
||||||
self.assertEquals(getattr(tm, cname), getattr(tm2, cname))
|
self.assertEquals(getattr(tm, cname), getattr(tm2, cname))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_model_updating_works_properly(self):
|
def test_model_updating_works_properly(self):
|
||||||
"""
|
"""
|
||||||
Tests that subsequent saves after initial model creation work
|
Tests that subsequent saves after initial model creation work
|
||||||
|
|||||||
Reference in New Issue
Block a user