| Index: boto/sdb/db/property.py
|
| diff --git a/boto/sdb/db/property.py b/boto/sdb/db/property.py
|
| index ab4f7a8138d94dd7588ca834da25bb70f53893a4..1929a02722640f4f18ef32f1a85d2992d966ec2c 100644
|
| --- a/boto/sdb/db/property.py
|
| +++ b/boto/sdb/db/property.py
|
| @@ -75,7 +75,7 @@ class Property(object):
|
| self.slot_name = '_' + self.name
|
|
|
| def default_validator(self, value):
|
| - if value == self.default_value():
|
| + if isinstance(value, basestring) or value == self.default_value():
|
| return
|
| if not isinstance(value, self.data_type):
|
| raise TypeError, 'Validation Error, expecting %s, got %s' % (self.data_type, type(value))
|
| @@ -135,6 +135,7 @@ class TextProperty(Property):
|
| self.max_length = max_length
|
|
|
| def validate(self, value):
|
| + value = super(TextProperty, self).validate(value)
|
| if not isinstance(value, str) and not isinstance(value, unicode):
|
| raise TypeError, 'Expecting Text, got %s' % type(value)
|
| if self.max_length and len(value) > self.max_length:
|
| @@ -142,18 +143,67 @@ class TextProperty(Property):
|
|
|
| class PasswordProperty(StringProperty):
|
| """
|
| - Hashed property who's original value can not be
|
| - retrieved, but still can be compaired.
|
| +
|
| + Hashed property whose original value can not be
|
| + retrieved, but still can be compared.
|
| +
|
| + Works by storing a hash of the original value instead
|
| + of the original value. Once that's done all that
|
| + can be retrieved is the hash.
|
| +
|
| + The comparison
|
| +
|
| + obj.password == 'foo'
|
| +
|
| + generates a hash of 'foo' and compares it to the
|
| + stored hash.
|
| +
|
| + Underlying data type for hashing, storing, and comparing
|
| + is boto.utils.Password. The default hash function is
|
| + defined there ( currently sha512 in most cases, md5
|
| + where sha512 is not available )
|
| +
|
| + It's unlikely you'll ever need to use a different hash
|
| + function, but if you do, you can control the behavior
|
| + in one of two ways:
|
| +
|
| + 1) Specifying hashfunc in PasswordProperty constructor
|
| +
|
| + import hashlib
|
| +
|
| + class MyModel(model):
|
| + password = PasswordProperty(hashfunc=hashlib.sha224)
|
| +
|
| + 2) Subclassing Password and PasswordProperty
|
| +
|
| + class SHA224Password(Password):
|
| + hashfunc=hashlib.sha224
|
| +
|
| + class SHA224PasswordProperty(PasswordProperty):
|
| + data_type=MyPassword
|
| + type_name="MyPassword"
|
| +
|
| + class MyModel(Model):
|
| + password = SHA224PasswordProperty()
|
| +
|
| """
|
| data_type = Password
|
| type_name = 'Password'
|
|
|
| def __init__(self, verbose_name=None, name=None, default='', required=False,
|
| - validator=None, choices=None, unique=False):
|
| + validator=None, choices=None, unique=False, hashfunc=None):
|
| +
|
| + """
|
| + The hashfunc parameter overrides the default hashfunc in boto.utils.Password.
|
| +
|
| + The remaining parameters are passed through to StringProperty.__init__"""
|
| +
|
| +
|
| StringProperty.__init__(self, verbose_name, name, default, required, validator, choices, unique)
|
| + self.hashfunc=hashfunc
|
|
|
| def make_value_from_datastore(self, value):
|
| - p = Password(value)
|
| + p = self.data_type(value, hashfunc=self.hashfunc)
|
| return p
|
|
|
| def get_value_for_datastore(self, model_instance):
|
| @@ -164,22 +214,22 @@ class PasswordProperty(StringProperty):
|
| return None
|
|
|
| def __set__(self, obj, value):
|
| - if not isinstance(value, Password):
|
| - p = Password()
|
| + if not isinstance(value, self.data_type):
|
| + p = self.data_type(hashfunc=self.hashfunc)
|
| p.set(value)
|
| value = p
|
| Property.__set__(self, obj, value)
|
|
|
| def __get__(self, obj, objtype):
|
| - return Password(StringProperty.__get__(self, obj, objtype))
|
| + return self.data_type(StringProperty.__get__(self, obj, objtype), hashfunc=self.hashfunc)
|
|
|
| def validate(self, value):
|
| value = Property.validate(self, value)
|
| - if isinstance(value, Password):
|
| + if isinstance(value, self.data_type):
|
| if len(value) > 1024:
|
| raise ValueError, 'Length of value greater than maxlength'
|
| else:
|
| - raise TypeError, 'Expecting Password, got %s' % type(value)
|
| + raise TypeError, 'Expecting %s, got %s' % (type(self.data_type), type(value))
|
|
|
| class BlobProperty(Property):
|
| data_type = Blob
|
| @@ -208,6 +258,7 @@ class S3KeyProperty(Property):
|
| validator, choices, unique)
|
|
|
| def validate(self, value):
|
| + value = super(S3KeyProperty, self).validate(value)
|
| if value == self.default_value() or value == str(self.default_value()):
|
| return self.default_value()
|
| if isinstance(value, self.data_type):
|
| @@ -340,6 +391,7 @@ class DateTimeProperty(Property):
|
| return Property.default_value(self)
|
|
|
| def validate(self, value):
|
| + value = super(DateTimeProperty, self).validate(value)
|
| if value == None:
|
| return
|
| if not isinstance(value, self.data_type):
|
| @@ -370,6 +422,7 @@ class DateProperty(Property):
|
| return Property.default_value(self)
|
|
|
| def validate(self, value):
|
| + value = super(DateProperty, self).validate(value)
|
| if value == None:
|
| return
|
| if not isinstance(value, self.data_type):
|
| @@ -386,6 +439,23 @@ class DateProperty(Property):
|
| def now(self):
|
| return datetime.date.today()
|
|
|
| +
|
| +class TimeProperty(Property):
|
| + data_type = datetime.time
|
| + type_name = 'Time'
|
| +
|
| + def __init__(self, verbose_name=None, name=None,
|
| + default=None, required=False, validator=None, choices=None, unique=False):
|
| + Property.__init__(self, verbose_name, name, default, required, validator, choices, unique)
|
| +
|
| + def validate(self, value):
|
| + value = super(TimeProperty, self).validate(value)
|
| + if value is None:
|
| + return
|
| + if not isinstance(value, self.data_type):
|
| + raise TypeError, 'Validation Error, expecting %s, got %s' % (self.data_type, type(value))
|
| +
|
| +
|
| class ReferenceProperty(Property):
|
|
|
| data_type = Key
|
| @@ -443,6 +513,8 @@ class ReferenceProperty(Property):
|
| raise ValueError, '%s is not a Model' % value
|
|
|
| def validate(self, value):
|
| + if self.validator:
|
| + self.validator(value)
|
| if self.required and value==None:
|
| raise ValueError, '%s is a required property' % self.name
|
| if value == self.default_value():
|
| @@ -528,6 +600,8 @@ class ListProperty(Property):
|
| Property.__init__(self, verbose_name, name, default=default, required=True, **kwds)
|
|
|
| def validate(self, value):
|
| + if self.validator:
|
| + self.validator(value)
|
| if value is not None:
|
| if not isinstance(value, list):
|
| value = [value]
|
| @@ -581,6 +655,7 @@ class MapProperty(Property):
|
| Property.__init__(self, verbose_name, name, default=default, required=True, **kwds)
|
|
|
| def validate(self, value):
|
| + value = super(MapProperty, self).validate(value)
|
| if value is not None:
|
| if not isinstance(value, dict):
|
| raise ValueError, 'Value must of type dict'
|
|
|