179 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #column field types
 | |
| import re
 | |
| from uuid import uuid1, uuid4
 | |
| 
 | |
| from cassandraengine.exceptions import ValidationError
 | |
| 
 | |
| class BaseColumn(object):
 | |
| 
 | |
|     #the cassandra type this column maps to
 | |
|     db_type = None
 | |
| 
 | |
|     def __init__(self, primary_key=False, db_field=None, default=None, null=False):
 | |
|         """
 | |
|         :param primary_key: bool flag, there can be only one primary key per doc
 | |
|         :param db_field: the fieldname this field will map to in the database
 | |
|         :param default: the default value, can be a value or a callable (no args)
 | |
|         :param null: boolean, is the field nullable?
 | |
|         """
 | |
|         self.primary_key = primary_key
 | |
|         self.db_field = db_field
 | |
|         self.default = default
 | |
|         self.null = null
 | |
| 
 | |
|     def validate(self, value):
 | |
|         """
 | |
|         Returns a cleaned and validated value. Raises a ValidationError
 | |
|         if there's a problem
 | |
|         """
 | |
|         if value is None:
 | |
|             if self.has_default:
 | |
|                 return self.get_default()
 | |
|             elif not self.null:
 | |
|                 raise ValidationError('null values are not allowed')
 | |
|         return value
 | |
| 
 | |
|     def to_python(self, value):
 | |
|         """
 | |
|         Converts data from the database into python values
 | |
|         raises a ValidationError if the value can't be converted
 | |
|         """
 | |
|         return value
 | |
| 
 | |
|     @property
 | |
|     def has_default(self):
 | |
|         return bool(self.default)
 | |
| 
 | |
|     @property
 | |
|     def is_primary_key(self):
 | |
|         return self.primary_key
 | |
| 
 | |
|     def get_default(self):
 | |
|         if self.has_default:
 | |
|             if callable(self.default):
 | |
|                 return self.default()
 | |
|             else:
 | |
|                 return self.default
 | |
| 
 | |
|     def to_database(self, value):
 | |
|         """
 | |
|         Converts python value into database value
 | |
|         """
 | |
|         if value is None and self.has_default:
 | |
|             return self.get_default()
 | |
|         return value
 | |
| 
 | |
|     def get_column_def(self):
 | |
|         """
 | |
|         Returns a column definition for CQL table definition
 | |
|         """
 | |
|         dterms = [self.db_field, self.db_type]
 | |
|         if self.primary_key:
 | |
|             dterms.append('PRIMARY KEY')
 | |
|         return ' '.join(dterms)
 | |
| 
 | |
|     def set_db_name(self, name):
 | |
|         """
 | |
|         Sets the column name during document class construction
 | |
|         This value will be ignored if db_field is set in __init__
 | |
|         """
 | |
|         self.db_field = self.db_field or name
 | |
| 
 | |
| class Bytes(BaseColumn):
 | |
|     db_type = 'blob'
 | |
| 
 | |
| class Ascii(BaseColumn):
 | |
|     db_type = 'ascii'
 | |
| 
 | |
| class Text(BaseColumn):
 | |
|     db_type = 'text'
 | |
| 
 | |
| class Integer(BaseColumn):
 | |
|     db_type = 'int'
 | |
| 
 | |
|     def validate(self, value):
 | |
|         val = super(Integer, self).validate(value)
 | |
|         try:
 | |
|             return long(val)
 | |
|         except (TypeError, ValueError):
 | |
|             raise ValidationError("{} can't be converted to integral value".format(value))
 | |
| 
 | |
|     def to_python(self, value):
 | |
|         return self.validate(value)
 | |
| 
 | |
|     def to_database(self, value):
 | |
|         return self.validate(value)
 | |
| 
 | |
| class DateTime(BaseColumn):
 | |
|     db_type = 'timestamp'
 | |
|     def __init__(self, **kwargs):
 | |
|         super(DateTime, self).__init__(**kwargs)
 | |
|         raise NotImplementedError
 | |
| 
 | |
| class UUID(BaseColumn):
 | |
|     """
 | |
|     Type 1 or 4 UUID
 | |
|     """
 | |
|     db_type = 'uuid'
 | |
| 
 | |
|     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)
 | |
|         from uuid import UUID as _UUID
 | |
|         if isinstance(val, _UUID): return val
 | |
|         if not self.re_uuid.match(val):
 | |
|             raise ValidationError("{} is not a valid uuid".format(value))
 | |
|         return _UUID(val)
 | |
| 
 | |
| class Boolean(BaseColumn):
 | |
|     db_type = 'boolean'
 | |
| 
 | |
|     def to_python(self, value):
 | |
|         return bool(value)
 | |
| 
 | |
|     def to_database(self, value):
 | |
|         return bool(value)
 | |
| 
 | |
| class Float(BaseColumn):
 | |
|     db_type = 'double'
 | |
| 
 | |
|     def validate(self, value):
 | |
|         try:
 | |
|             return float(value)
 | |
|         except (TypeError, ValueError):
 | |
|             raise ValidationError("{} is not a valid float".format(value))
 | |
| 
 | |
|     def to_python(self, value):
 | |
|         return self.validate(value)
 | |
| 
 | |
|     def to_database(self, value):
 | |
|         return self.validate(value)
 | |
| 
 | |
| class Decimal(BaseColumn):
 | |
|     db_type = 'decimal'
 | |
|     #TODO: this
 | |
|     def __init__(self, **kwargs):
 | |
|         super(DateTime, self).__init__(**kwargs)
 | |
|         raise NotImplementedError
 | |
| 
 | |
| class Counter(BaseColumn):
 | |
|     def __init__(self, **kwargs):
 | |
|         super(DateTime, self).__init__(**kwargs)
 | |
|         raise NotImplementedError
 | |
| 
 | |
| #TODO: research supercolumns
 | |
| #http://wiki.apache.org/cassandra/DataModel
 | |
| class List(BaseColumn):
 | |
|     def __init__(self, **kwargs):
 | |
|         super(DateTime, self).__init__(**kwargs)
 | |
|         raise NotImplementedError
 | |
| 
 | |
| class Dict(BaseColumn):
 | |
|     def __init__(self, **kwargs):
 | |
|         super(DateTime, self).__init__(**kwargs)
 | |
|         raise NotImplementedError
 | 
