Added a MonthYear field, fixed some field required values and fixed

validation functions. Added numeric state abbreviation capability.
So far everything appears to be working good.
This commit is contained in:
Binh 2011-06-04 15:46:41 -05:00
parent 5781cbf335
commit a0014ca451
4 changed files with 173 additions and 35 deletions

121
fields.py
View file

@ -1,7 +1,17 @@
import decimal, datetime
import inspect
from enums import STATE_POSTAL_NUMERIC
class ValidationError(Exception):
pass
def __init__(self, msg, field=None):
self.msg = msg
self.field = field
def __str__(self):
if self.field:
return "(%s.%s) %s" % (self.field.parent_name, self.field.name, self.msg)
else:
return repr(self.msg)
class Field(object):
creation_counter = 0
@ -42,9 +52,9 @@ class Field(object):
class TextField(Field):
def validate(self):
if self.value == None and self.required:
raise ValidationError("value required")
if len(self.value) > self.max_length:
raise ValidationError("value is too long")
raise ValidationError("value required", field=self)
if len(self.get_data()) > self.max_length:
raise ValidationError("value is too long", field=self)
def get_data(self):
value = self.value or ""
@ -54,9 +64,28 @@ class TextField(Field):
class StateField(TextField):
def __init__(self, name=None, required=True):
return super(StateField, self).__init__(name=name, max_length=2, required=required)
def __init__(self, name=None, required=True, use_numeric=False):
super(StateField, self).__init__(name=name, max_length=2, required=required)
self.use_numeric = use_numeric
def get_data(self):
value = self.value or ""
if value.strip() and self.use_numeric:
return str(STATE_POSTAL_NUMERIC[value.upper()]).zfill(self.max_length)
else:
return value.ljust(self.max_length).encode('ascii')
def validate(self):
super(StateField, self).validate()
if self.value and self.value.upper() not in STATE_POSTAL_NUMERIC.keys():
raise ValidationError("%s is not a valid state abbreviation" % self.value, field=self)
def parse(self, s):
if s.strip() and self.use_numeric:
states = dict( [(v,k) for (k,v) in STATE_POSTAL_NUMERIC.items()] )
self.value = states[int(s)]
else:
self.value = s
class EmailField(TextField):
def __init__(self, name=None, required=True, max_length=None):
@ -66,14 +95,16 @@ class EmailField(TextField):
class NumericField(TextField):
def validate(self):
super(NumericField, self).validate()
try:
int(self.value)
except ValueError:
raise ValidationError("field contains non-numeric characters")
if self.value:
try:
int(self.value)
except ValueError:
raise ValidationError("field contains non-numeric characters", field=self)
def get_data(self):
value = self.value or ""
return value.zfill(self.max_length)
return str(value).zfill(self.max_length)
def parse(self, s):
self.value = int(s)
@ -89,6 +120,9 @@ class StaticField(TextField):
pass
class BlankField(TextField):
def __init__(self, name=None, max_length=0, required=False):
super(TextField, self).__init__(name=name, max_length=max_length, required=required, uppercase=False)
def get_data(self):
return " " * self.max_length
@ -109,12 +143,13 @@ class BooleanField(Field):
def parse(self, s):
self.value = (s == '1')
class MoneyField(Field):
def validate(self):
if self.value == None and self.required:
raise ValidationError("value required")
raise ValidationError("value required", field=self)
if len(str(int((self.value or 0)*100))) > self.max_length:
raise ValidationError("value is too long")
raise ValidationError("value is too long", field=self)
def get_data(self):
return str(int((self.value or 0)*100)).encode('ascii').zfill(self.max_length)
@ -122,15 +157,12 @@ class MoneyField(Field):
def parse(self, s):
self.value = decimal.Decimal(s) * decimal.Decimal('0.01')
class DateField(TextField):
def __init__(self, name=None, required=True, value=None):
super(TextField, self).__init__(name=name, required=required, max_length=8)
if isinstance(value, datetime.date):
self._value = value
elif value:
self._value = datetime.date(*[int(x) for x in value[4:8], value[0:2], value[2:4]])
else:
self._value = None
super(TextField, self).__init__(name=name, required=required, max_length=8)
if value:
self.value = value
def get_data(self):
if self._value:
@ -138,6 +170,53 @@ class DateField(TextField):
return '0' * self.max_length
def parse(self, s):
self.value = datetime.date(*[int(x) for x in s[4:8], s[0:2], s[2:4]])
if int(s) > 0:
self.value = datetime.date(*[int(x) for x in s[4:8], s[0:2], s[2:4]])
else:
self.value = None
def __setvalue(self, value):
if isinstance(value, datetime.date):
self._value = value
elif value:
self._value = datetime.date(*[int(x) for x in value[4:8], value[0:2], value[2:4]])
else:
self._value = None
def __getvalue(self):
return self._value
value = property(__getvalue, __setvalue)
class MonthYearField(TextField):
def __init__(self, name=None, required=True, value=None):
super(TextField, self).__init__(name=name, required=required, max_length=6)
if value:
self.value = value
def get_data(self):
if self._value:
return self._value.strftime("%m%Y")
return '0' * self.max_length
def parse(self, s):
if int(s) > 0:
self.value = datetime.date(*[int(x) for x in s[2:6], s[0:2], 1])
else:
self.value = None
def __setvalue(self, value):
if isinstance(value, datetime.date):
self._value = value
elif value:
self._value = datetime.date(*[int(x) for x in value[2:6], value[0:2], 1])
else:
self._value = None
def __getvalue(self):
return self._value
value = property(__getvalue, __setvalue)