S
Sarcastic Zombie
Code included below.
Basically, I've created a series of "question" descriptors, which each
hold a managed value. This is so I can implement validation, and render
each field into html automatically for forms.
My problem is this: every instance of my "wizard" class has unique self
values, but they share the exact same descriptor values.
Meaning, if
t = Test("ar")
y = Test("ar")
t is y
False
t.age is y.age
True
t.age = 9
y.age
9
Code below. What am I not understanding?
-----------------------------------------
import datetime, re
class Question(object):
def __init__(self, qtext, name, default=None, required=False,
max_length=None, choices=None):
self._name = name
self._qtext = qtext
self._value = default
self._error = None
self._max_length = max_length
self._required = required
self._choices = choices
def __get__(self, instance, owner):
return self
def __set__(self, instance, value):
error = self.validate(value)
if not error:
self._value = self.cast(value)
self._error = None
else:
self._value = value
self._error = error
print error
def __str__(self):
return str(self._value)
def __repr__(self):
return str(self._value)
def cast(self, value):
return value
def validate(self, value):
return True
def html(self):
#ugly html renderer removed; irrelevant to problem
return html
def error(self):
if self._error:
return True
class Q_Integer(Question):
def validate(self, value):
if self._required and not value:
return "Field is required."
elif not value:
return None
try:
int(value)
return None
except:
return "Answer must be a whole number."
def cast(self, value):
if value:
return int(value)
class Q_Float(Question):
def validate(self, value):
if self._required and not value:
return "Field is required."
elif not value:
return None
try:
float(value)
return None
except:
return "Answer must be a decimal number."
def cast(self, value):
if value:
return float(value)
class Q_Chars(Question):
def validate(self, value):
try:
if self._required and not value:
return "Field is required."
elif not value:
return None
if self._max_length:
if len(value) > self._max_length:
return "Too many characters; max of %s allowed." %
self._max_length
return None
except:
return "Invalid entry."
def cast(self, value):
if value:
return str(value)
class Q_Long(Question):
def validate(self, value):
try:
if self._required and not value:
return "Field is required."
elif not value:
return None
except:
return "Invalid entry."
def cast(self, value):
if value:
return str(value)
def html(self):
#ugly html renderer removed; irrelevant to problem
return html
class Q_Bool(Question):
def validate(self, value):
return None
def cast(self, value):
return bool(value)
def html(self):
#ugly html renderer removed; irrelevant to problem
return html
class Q_Phone(Question):
def validate(self, value):
try:
if self._required and not value:
return "Field is required."
elif not value:
return None
pieces = value.split("-")
if len(pieces[0]) == 3 and len(pieces[1]) == 3 and len(pieces[2]) ==
4:
int(pieces[0])
int(pieces[1])
int(pieces[2])
return None
else:
return "Requires Valid Phone Number in XXX-XXX-XXXX format."
except:
return "Requires Valid Phone Number in XXX-XXX-XXXX format."
class Q_Date(Question):
def validate(self, value):
try:
if self._required and not value:
return "Field is required."
elif not value:
return None
r = re.compile(r"\d{1,2}[-/.]\d{1,2}[-/.]\d{1,4}")
month, day, year =
r.findall(value)[0].replace("/","-").replace(".","-").split("-")
date = datetime.date(year=int(year), month=int(month), day=int(day)
)
return None
except:
return "Requires valid date in mm-dd-yy format."
def cast(self, value):
if value:
r = re.compile(r"\d{1,2}[-/.]\d{1,2}[-/.]\d{1,4}")
month, day, year =
r.findall(value)[0].replace("/","-").replace(".","-").split("-")
year = int(year)
if year < 70:
year += 2000
elif year < 100:
year += 1000
date = datetime.date(year=int(year), month=int(month), day=int(day)
)
return date
def __str__(self):
date = self._value
return "%s/%s/%s" % (date.month, date.day, date.year)
## Wizard Base Object
class Wizard(object):
def __init__(self, action):
self.action = action
self.init_time = datetime.datetime.now()
pagediv = "box"
title = "A Dynamic Wizard"
instructions = "There are no real instructions here. Sorry."
grouping = [ ]
def render_form(self):
#ugly html renderer removed; irrelevant to problem
return form
def flatten(self, post):
for key in post:
if not key == "command":
errors = ""
cblock = "self.%s = '%s'\n" % (key, post[key])
ab_save = compile( cblock, errors, 'exec')
exec(ab_save)
def errorcheck(self):
error = 0
for section in self.grouping:
for question in section:
t = eval( "self.%s.validate(self.%s._value)" % (question, question)
)
if t:
error = 1
return error
C_CHOICES = (
("red", "Red"),
("blue", "Blue"),
("green", "Green"),
)
class Test(Wizard):
grouping = [
[ 'age', 'weight' ],
[ 'feet', 'inches' ],
['name', 'cash', 'fav_color', 'happy', 'birthday'] ]
def __new__(self):
age = Q_Integer("Your Age:", "age", 99)
weight = Q_Integer("Your Weight:", "weight", 200)
feet = Q_Integer("Feet tall:", "feet", 6)
inches = Q_Integer("Inches Tall:", "inches", 0)
name = Q_Chars("Your Name:", "name", max_length=15, required=True)
cash = Q_Float("Money in hand?", "cash", required=True,
default=55.50)
fav_color = Q_Chars("Your favorite color?", "fav_color",
required=True, max_length=50, choices=C_CHOICES)
homezip = Q_Zip("Your zip code?", "homezip", required=True, )
happy = Q_Bool("Are you happy?", "happy", default=False)
birthday = Q_Date("Your Birthday:", "birthday")
Basically, I've created a series of "question" descriptors, which each
hold a managed value. This is so I can implement validation, and render
each field into html automatically for forms.
My problem is this: every instance of my "wizard" class has unique self
values, but they share the exact same descriptor values.
Meaning, if
t = Test("ar")
y = Test("ar")
t is y
False
t.age is y.age
True
t.age = 9
y.age
9
Code below. What am I not understanding?
-----------------------------------------
import datetime, re
class Question(object):
def __init__(self, qtext, name, default=None, required=False,
max_length=None, choices=None):
self._name = name
self._qtext = qtext
self._value = default
self._error = None
self._max_length = max_length
self._required = required
self._choices = choices
def __get__(self, instance, owner):
return self
def __set__(self, instance, value):
error = self.validate(value)
if not error:
self._value = self.cast(value)
self._error = None
else:
self._value = value
self._error = error
print error
def __str__(self):
return str(self._value)
def __repr__(self):
return str(self._value)
def cast(self, value):
return value
def validate(self, value):
return True
def html(self):
#ugly html renderer removed; irrelevant to problem
return html
def error(self):
if self._error:
return True
class Q_Integer(Question):
def validate(self, value):
if self._required and not value:
return "Field is required."
elif not value:
return None
try:
int(value)
return None
except:
return "Answer must be a whole number."
def cast(self, value):
if value:
return int(value)
class Q_Float(Question):
def validate(self, value):
if self._required and not value:
return "Field is required."
elif not value:
return None
try:
float(value)
return None
except:
return "Answer must be a decimal number."
def cast(self, value):
if value:
return float(value)
class Q_Chars(Question):
def validate(self, value):
try:
if self._required and not value:
return "Field is required."
elif not value:
return None
if self._max_length:
if len(value) > self._max_length:
return "Too many characters; max of %s allowed." %
self._max_length
return None
except:
return "Invalid entry."
def cast(self, value):
if value:
return str(value)
class Q_Long(Question):
def validate(self, value):
try:
if self._required and not value:
return "Field is required."
elif not value:
return None
except:
return "Invalid entry."
def cast(self, value):
if value:
return str(value)
def html(self):
#ugly html renderer removed; irrelevant to problem
return html
class Q_Bool(Question):
def validate(self, value):
return None
def cast(self, value):
return bool(value)
def html(self):
#ugly html renderer removed; irrelevant to problem
return html
class Q_Phone(Question):
def validate(self, value):
try:
if self._required and not value:
return "Field is required."
elif not value:
return None
pieces = value.split("-")
if len(pieces[0]) == 3 and len(pieces[1]) == 3 and len(pieces[2]) ==
4:
int(pieces[0])
int(pieces[1])
int(pieces[2])
return None
else:
return "Requires Valid Phone Number in XXX-XXX-XXXX format."
except:
return "Requires Valid Phone Number in XXX-XXX-XXXX format."
class Q_Date(Question):
def validate(self, value):
try:
if self._required and not value:
return "Field is required."
elif not value:
return None
r = re.compile(r"\d{1,2}[-/.]\d{1,2}[-/.]\d{1,4}")
month, day, year =
r.findall(value)[0].replace("/","-").replace(".","-").split("-")
date = datetime.date(year=int(year), month=int(month), day=int(day)
)
return None
except:
return "Requires valid date in mm-dd-yy format."
def cast(self, value):
if value:
r = re.compile(r"\d{1,2}[-/.]\d{1,2}[-/.]\d{1,4}")
month, day, year =
r.findall(value)[0].replace("/","-").replace(".","-").split("-")
year = int(year)
if year < 70:
year += 2000
elif year < 100:
year += 1000
date = datetime.date(year=int(year), month=int(month), day=int(day)
)
return date
def __str__(self):
date = self._value
return "%s/%s/%s" % (date.month, date.day, date.year)
## Wizard Base Object
class Wizard(object):
def __init__(self, action):
self.action = action
self.init_time = datetime.datetime.now()
pagediv = "box"
title = "A Dynamic Wizard"
instructions = "There are no real instructions here. Sorry."
grouping = [ ]
def render_form(self):
#ugly html renderer removed; irrelevant to problem
return form
def flatten(self, post):
for key in post:
if not key == "command":
errors = ""
cblock = "self.%s = '%s'\n" % (key, post[key])
ab_save = compile( cblock, errors, 'exec')
exec(ab_save)
def errorcheck(self):
error = 0
for section in self.grouping:
for question in section:
t = eval( "self.%s.validate(self.%s._value)" % (question, question)
)
if t:
error = 1
return error
C_CHOICES = (
("red", "Red"),
("blue", "Blue"),
("green", "Green"),
)
class Test(Wizard):
grouping = [
[ 'age', 'weight' ],
[ 'feet', 'inches' ],
['name', 'cash', 'fav_color', 'happy', 'birthday'] ]
def __new__(self):
age = Q_Integer("Your Age:", "age", 99)
weight = Q_Integer("Your Weight:", "weight", 200)
feet = Q_Integer("Feet tall:", "feet", 6)
inches = Q_Integer("Inches Tall:", "inches", 0)
name = Q_Chars("Your Name:", "name", max_length=15, required=True)
cash = Q_Float("Money in hand?", "cash", required=True,
default=55.50)
fav_color = Q_Chars("Your favorite color?", "fav_color",
required=True, max_length=50, choices=C_CHOICES)
homezip = Q_Zip("Your zip code?", "homezip", required=True, )
happy = Q_Bool("Are you happy?", "happy", default=False)
birthday = Q_Date("Your Birthday:", "birthday")