fixed #67 (validation on keyname typos) #66 (removed defaults on columns) and #57 and removed autoid

This commit is contained in:
Jon Haddad
2013-06-14 17:52:13 -07:00
parent 35811d1fab
commit 4a977005f3
7 changed files with 69 additions and 33 deletions

View File

@@ -1,5 +1,9 @@
CHANGELOG
0.4.0
* removed default values from all column types
* explicit primary key is required (automatic id removed)
0.3.3
* added abstract base class models

View File

@@ -236,9 +236,6 @@ class Integer(Column):
class DateTime(Column):
db_type = 'timestamp'
def __init__(self, **kwargs):
super(DateTime, self).__init__(**kwargs)
def to_python(self, value):
if isinstance(value, datetime):
return value
@@ -265,8 +262,6 @@ class DateTime(Column):
class Date(Column):
db_type = 'timestamp'
def __init__(self, **kwargs):
super(Date, self).__init__(**kwargs)
def to_python(self, value):
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}')
def __init__(self, default=lambda:uuid4(), **kwargs):
super(UUID, self).__init__(default=default, **kwargs)
def validate(self, value):
val = super(UUID, self).validate(value)
if val is None: return
@@ -319,10 +311,6 @@ class TimeUUID(UUID):
db_type = 'timeuuid'
def __init__(self, **kwargs):
kwargs.setdefault('default', lambda: uuid1())
super(TimeUUID, self).__init__(**kwargs)
class Boolean(Column):
db_type = 'boolean'

View File

@@ -2,7 +2,7 @@ from collections import OrderedDict
import re
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 DoesNotExist as _DoesNotExist
from cqlengine.query import MultipleObjectsReturned as _MultipleObjectsReturned
@@ -50,7 +50,7 @@ class BaseModel(object):
"""
The base model class, don't inherit from this, inherit from Model, defined below
"""
class DoesNotExist(_DoesNotExist): pass
class MultipleObjectsReturned(_MultipleObjectsReturned): pass
@@ -60,12 +60,17 @@ class BaseModel(object):
#however, you can also define them manually here
table_name = None
#the keyspace for this model
#the keyspace for this model
keyspace = None
read_repair_chance = 0.1
def __init__(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():
value = values.get(name, None)
if value is not None: value = column.to_python(value)
@@ -111,11 +116,11 @@ class BaseModel(object):
else:
camelcase = re.compile(r'([a-z])([A-Z])')
ccase = lambda s: camelcase.sub(lambda v: '{}_{}'.format(v.group(1), v.group(2).lower()), s)
module = cls.__module__.split('.')
if module:
cf_name = ccase(module[-1]) + '_'
cf_name += ccase(cls.__name__)
#trim to less than 48 characters or cassandra will complain
cf_name = cf_name[-48:]
@@ -140,15 +145,15 @@ class BaseModel(object):
@classmethod
def create(cls, **kwargs):
return cls.objects.create(**kwargs)
@classmethod
def all(cls):
return cls.objects.all()
@classmethod
def filter(cls, **kwargs):
return cls.objects.filter(**kwargs)
@classmethod
def get(cls, **kwargs):
return cls.objects.get(**kwargs)
@@ -226,8 +231,7 @@ class ModelMetaClass(type):
#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]):
k,v = 'id', columns.UUID(primary_key=True)
column_definitions = [(k,v)] + column_definitions
raise ModelDefinitionException("At least 1 primary key is required.")
has_partition_keys = any(v.partition_key for (k, v) in column_definitions)

View File

@@ -3,6 +3,7 @@ from datetime import datetime, timedelta
from datetime import date
from datetime import tzinfo
from decimal import Decimal as D
from uuid import uuid4, uuid1
from cqlengine import ValidationError
from cqlengine.tests.base import BaseCassEngTestCase
@@ -119,7 +120,7 @@ class TestDecimal(BaseCassEngTestCase):
class TestTimeUUID(BaseCassEngTestCase):
class TimeUUIDTest(Model):
test_id = Integer(primary_key=True)
timeuuid = TimeUUID()
timeuuid = TimeUUID(default=uuid1())
@classmethod
def setUpClass(cls):
@@ -132,6 +133,10 @@ class TestTimeUUID(BaseCassEngTestCase):
delete_table(cls.TimeUUIDTest)
def test_timeuuid_io(self):
"""
ensures that
:return:
"""
t0 = self.TimeUUIDTest.create(test_id=0)
t1 = self.TimeUUIDTest.get(test_id=0)
@@ -139,8 +144,8 @@ class TestTimeUUID(BaseCassEngTestCase):
class TestInteger(BaseCassEngTestCase):
class IntegerTest(Model):
test_id = UUID(primary_key=True)
value = Integer(default=0)
test_id = UUID(primary_key=True, default=lambda:uuid4())
value = Integer(default=0, required=True)
def test_default_zero_fields_validate(self):
""" 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)

View File

@@ -1,8 +1,9 @@
from uuid import uuid4
from cqlengine.query import QueryException
from cqlengine.tests.base import BaseCassEngTestCase
from cqlengine.exceptions import ModelException, CQLEngineException
from cqlengine.models import Model
from cqlengine.models import Model, ModelDefinitionException
from cqlengine import columns
import cqlengine
@@ -18,6 +19,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
"""
class TestModel(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
text = columns.Text()
#check class attibutes
@@ -38,6 +40,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
-the db_map allows columns
"""
class WildDBNames(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
content = columns.Text(db_field='words_and_whatnot')
numbers = columns.Integer(db_field='integers_etc')
@@ -61,17 +64,26 @@ class TestModelClassFunction(BaseCassEngTestCase):
"""
class Stuff(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
words = columns.Text()
content = columns.Text()
numbers = columns.Integer()
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):
"""
Tests that instance value managers are isolated from other instances
"""
class Stuff(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
num = columns.Integer()
inst1 = Stuff(num=5)
@@ -86,6 +98,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
Tests that fields defined on the super class are inherited properly
"""
class TestModel(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
text = columns.Text()
class InheritedModel(TestModel):
@@ -124,6 +137,7 @@ class TestModelClassFunction(BaseCassEngTestCase):
Test compound partition key definition
"""
class ModelWithPartitionKeys(cqlengine.Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
c1 = cqlengine.Text(primary_key=True)
p1 = 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):
""" Tests that columns that can be deleted have the del attribute """
class DelModel(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
key = columns.Integer(primary_key=True)
data = columns.Integer(required=False)
@@ -156,9 +171,10 @@ class TestModelClassFunction(BaseCassEngTestCase):
""" Tests that DoesNotExist exceptions are not the same exception between models """
class Model1(Model):
pass
id = columns.UUID(primary_key=True, default=lambda:uuid4())
class Model2(Model):
pass
id = columns.UUID(primary_key=True, default=lambda:uuid4())
try:
raise Model1.DoesNotExist
@@ -171,7 +187,8 @@ class TestModelClassFunction(BaseCassEngTestCase):
def test_does_not_exist_inherits_from_superclass(self):
""" Tests that a DoesNotExist exception can be caught by it's parent class DoesNotExist """
class Model1(Model):
pass
id = columns.UUID(primary_key=True, default=lambda:uuid4())
class Model2(Model1):
pass
@@ -184,14 +201,14 @@ class TestModelClassFunction(BaseCassEngTestCase):
assert False, "Model2 exception should not be caught by Model1"
class TestManualTableNaming(BaseCassEngTestCase):
class RenamedTest(cqlengine.Model):
keyspace = 'whatever'
table_name = 'manual_name'
id = cqlengine.UUID(primary_key=True)
data = cqlengine.Text()
def test_proper_table_naming(self):
assert self.RenamedTest.column_family_name(include_keyspace=False) == 'manual_name'
assert self.RenamedTest.column_family_name(include_keyspace=True) == 'whatever.manual_name'

View File

@@ -1,4 +1,5 @@
from unittest import skip
from uuid import uuid4
from cqlengine.tests.base import BaseCassEngTestCase
from cqlengine.management import create_table
@@ -7,6 +8,7 @@ from cqlengine.models import Model
from cqlengine import columns
class TestModel(Model):
id = columns.UUID(primary_key=True, default=lambda:uuid4())
count = columns.Integer()
text = columns.Text(required=False)

View File

@@ -8,10 +8,18 @@ from cqlengine.models import Model
from cqlengine import columns
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 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):
@classmethod
@@ -34,6 +42,8 @@ class TestModelIO(BaseCassEngTestCase):
for cname in tm._columns.keys():
self.assertEquals(getattr(tm, cname), getattr(tm2, cname))
def test_model_updating_works_properly(self):
"""
Tests that subsequent saves after initial model creation work