Changeset 12306 for main/waeup.ikoba/trunk/src
- Timestamp:
- 24 Dec 2014, 07:38:53 (10 years ago)
- Location:
- main/waeup.ikoba/trunk/src/waeup/ikoba
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.ikoba/trunk/src/waeup/ikoba/interfaces.py
r12260 r12306 86 86 SimpleTerm(value, value, title) for title, value in terms]) 87 87 88 currencies = SimpleIkobaVocabulary( 89 (_('Naira'),'naira'), 90 (_('USD'),'usd'), 91 (_('EUR'),'eur'), 92 ) 88 93 89 94 class ContextualDictSourceFactoryBase(SmartBasicContextualSourceFactory): … … 105 110 utils = getUtility(IIkobaUtils) 106 111 return getattr(utils, self.DICT_NAME)[value] 107 108 class SubjectSource(BasicSourceFactory):109 """A source for school subjects used in exam documentation.110 """111 def getValues(self):112 subjects_dict = getUtility(IIkobaUtils).EXAM_SUBJECTS_DICT113 return sorted(subjects_dict.keys())114 115 def getTitle(self, value):116 subjects_dict = getUtility(IIkobaUtils).EXAM_SUBJECTS_DICT117 return "%s:" % subjects_dict[value]118 119 class GradeSource(BasicSourceFactory):120 """A source for exam grades.121 """122 def getValues(self):123 for entry in getUtility(IIkobaUtils).EXAM_GRADES:124 yield entry[0]125 126 def getTitle(self, value):127 return dict(getUtility(IIkobaUtils).EXAM_GRADES)[value]128 112 129 113 # Define a validation method for email addresses … … 227 211 return value 228 212 229 class I ResultEntry(Interface):213 class IProductOptionEntry(Interface): 230 214 """A school grade entry. 231 215 """ 232 subject = schema.Choice( 233 title = _(u'Subject'), 234 source = SubjectSource(), 235 ) 236 grade = schema.Choice( 237 title = _(u'Grade'), 238 source = GradeSource(), 239 ) 240 241 class IResultEntryField(IObject): 216 title = schema.TextLine( 217 title = _(u'Title'), 218 required = True, 219 ) 220 fee = schema.Decimal( 221 title = _(u'Fee'), 222 required = False, 223 ) 224 currency = schema.Choice( 225 title = _(u'Currency'), 226 vocabulary = currencies, 227 required = False, 228 ) 229 230 class IProductOptionEntryField(IObject): 242 231 """A zope.schema-like field for usage in interfaces. 243 232 244 Marker interface to distuingish resultentries from ordinary233 Marker interface to distuingish product option entries from ordinary 245 234 object fields. Needed for registration of widgets. 246 235 """ … … 252 241 PORTAL_LANGUAGE = Attribute("Dict of global language setting") 253 242 PREFERRED_LANGUAGES_DICT = Attribute("Dict of preferred languages") 254 EXAM_SUBJECTS_DICT = Attribute("Dict of examination subjects")255 EXAM_GRADES = Attribute("Dict of examination grades")256 243 SYSTEM_MAX_LOAD = Attribute("Dict of maximum system loads.") 257 244 -
main/waeup.ikoba/trunk/src/waeup/ikoba/schoolgrades.py
r11949 r12306 16 16 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 17 ## 18 """Components representing and aggregating school grades.18 """Components representing and aggregating product options. 19 19 """ 20 20 import grok 21 from decimal import Decimal 21 22 from zope.formlib.interfaces import IInputWidget, IDisplayWidget 22 23 from zope.publisher.interfaces.browser import IBrowserRequest 23 24 from zope.schema.fieldproperty import FieldProperty 24 25 from zope.schema import Object 25 from waeup.ikoba.interfaces import I ResultEntry, IResultEntryField26 from waeup.ikoba.interfaces import IProductOptionEntry, IProductOptionEntryField 26 27 from waeup.ikoba.widgets.objectwidget import ( 27 28 IkobaObjectWidget, IkobaObjectDisplayWidget 28 29 ) 29 30 30 class ResultEntry(grok.Model):31 """A result entry contains a subject and a grade.31 class ProductOptionEntry(grok.Model): 32 """A product option entry contains a title, fee and currency. 32 33 """ 33 grok.implements(IResultEntry) 34 subject = FieldProperty(IResultEntry['subject']) 35 grade = FieldProperty(IResultEntry['grade']) 34 grok.implements(IProductOptionEntry) 35 title = FieldProperty(IProductOptionEntry['title']) 36 fee = FieldProperty(IProductOptionEntry['fee']) 37 currency = FieldProperty(IProductOptionEntry['currency']) 36 38 37 def __init__(self, subject=None, grade=None): 38 super(ResultEntry, self).__init__() 39 if subject is not None: 40 self.subject = subject 41 if grade is not None: 42 self.grade = grade 39 def __init__(self, title=None, fee=None, currency=None): 40 super(ProductOptionEntry, self).__init__() 41 if title is not None: 42 self.title = title 43 if fee is not None: 44 self.fee = fee 45 if currency is not None: 46 self.currency = currency 43 47 return 44 48 … … 46 50 """A string representation that can be used in exports. 47 51 48 Returned is a unicode string of format ``(u'< SUBJ>',u'<GRADE>')``.52 Returned is a unicode string of format ``(u'<TITLE>',u'<FEE>',u'<CURR>')``. 49 53 """ 50 return unicode((self.subject, self.grade)) 54 string = u"(u'%s', u'%s', u'%s')" % (self.title, self.fee, self.currency) 55 string = string.replace("u'None'", "None") 56 return string 51 57 52 58 @classmethod 53 59 def from_string(cls, string): 54 """Create new ResultEntry instance based on `string`.60 """Create new ProductOptionEntry instance based on `string`. 55 61 56 62 The string is expected to be in format as delivered by … … 59 65 This is a classmethod. This means, you normally will call:: 60 66 61 ResultEntry.from_string(mystring)67 ProductOptionEntry.from_string(mystring) 62 68 63 i.e. use the ` ResultEntry` class, not an instance thereof.69 i.e. use the `ProductOptionEntry` class, not an instance thereof. 64 70 """ 65 71 string = string.replace("u''", "None") 66 subject, grade = eval(string) 67 return cls(subject, grade) 72 title, fee, currency = eval(string) 73 try: 74 fee = Decimal(fee) 75 except TypeError: 76 pass 77 return cls(title, fee, currency) 68 78 69 class ResultEntryField(Object):79 class ProductOptionEntryField(Object): 70 80 """A zope.schema-like field for usage in interfaces. 71 81 … … 74 84 75 85 class IMyInterface(Interface): 76 my_ result_entry = ResultEntryField()86 my_option_entry = ProductOptionEntryField() 77 87 78 88 Default widgets are registered to render result entry fields. 79 89 """ 80 grok.implements(I ResultEntryField)90 grok.implements(IProductOptionEntryField) 81 91 82 92 def __init__(self, **kw): 83 super( ResultEntryField, self).__init__(IResultEntry, **kw)93 super(ProductOptionEntryField, self).__init__(IProductOptionEntry, **kw) 84 94 return 85 95 86 # register IkobaObjectWidgets as default widgets for I ResultEntryFields87 @grok.adapter(I ResultEntryField, IBrowserRequest)96 # register IkobaObjectWidgets as default widgets for IProductOptionEntryFields 97 @grok.adapter(IProductOptionEntryField, IBrowserRequest) 88 98 @grok.implementer(IInputWidget) 89 99 def result_entry_input_widget(obj, req): 90 return IkobaObjectWidget(obj, req, ResultEntry)100 return IkobaObjectWidget(obj, req, ProductOptionEntry) 91 101 92 # register a display widget for I ResultEntryFields93 @grok.adapter(I ResultEntryField, IBrowserRequest)102 # register a display widget for IProductOptionEntryFields 103 @grok.adapter(IProductOptionEntryField, IBrowserRequest) 94 104 @grok.implementer(IDisplayWidget) 95 105 def result_entry_display_widget(obj, req): 96 return IkobaObjectDisplayWidget(obj, req, ResultEntry)106 return IkobaObjectDisplayWidget(obj, req, ProductOptionEntry) -
main/waeup.ikoba/trunk/src/waeup/ikoba/tests/test_schoolgrades.py
r11949 r12306 1 1 # Tests for schoolgrades module. 2 2 import unittest 3 from decimal import Decimal 3 4 from zope.component import getGlobalSiteManager 4 5 from zope.interface.verify import verifyObject, verifyClass 5 from zope.schema.interfaces import ConstraintNotSatisfied 6 from waeup.ikoba.interfaces import I ResultEntry, IResultEntryField, IIkobaUtils7 from waeup.ikoba.schoolgrades import ResultEntry, ResultEntryField6 from zope.schema.interfaces import ConstraintNotSatisfied, WrongType 7 from waeup.ikoba.interfaces import IProductOptionEntry, IProductOptionEntryField, IIkobaUtils 8 from waeup.ikoba.schoolgrades import ProductOptionEntry, ProductOptionEntryField 8 9 from waeup.ikoba.utils.utils import IkobaUtils 9 10 10 class ResultEntryTests(unittest.TestCase):11 class ProductOptionEntryTests(unittest.TestCase): 11 12 12 13 def setUp(self): … … 14 15 self.gsm = getGlobalSiteManager() 15 16 self.gsm.registerUtility(self.utils, IIkobaUtils) 16 self.valid_subj = self.utils.EXAM_SUBJECTS_DICT.keys()[0] 17 self.valid_grade = self.utils.EXAM_GRADES[0][0] 17 self.valid_title = u'Option 1' 18 self.valid_fee = Decimal(55.5) 19 self.valid_currency = 'usd' 18 20 return 19 21 … … 24 26 def test_ifaces(self): 25 27 # make sure we implement the promised interfaces. 26 obj = ResultEntry()27 verifyObject(I ResultEntry, obj)28 verifyClass(I ResultEntry, ResultEntry)28 obj = ProductOptionEntry() 29 verifyObject(IProductOptionEntry, obj) 30 verifyClass(IProductOptionEntry, ProductOptionEntry) 29 31 return 30 32 31 33 def test_init(self): 32 34 # we can pass initial values 33 item1 = ResultEntry() 34 item2 = ResultEntry(self.valid_subj, self.valid_grade) 35 self.assertTrue(item1.subject is None) 36 self.assertTrue(item1.grade is None) 37 self.assertEqual(item2.subject, self.valid_subj) 38 self.assertEqual(item2.grade, self.valid_grade) 35 item1 = ProductOptionEntry() 36 item2 = ProductOptionEntry( 37 self.valid_title, self.valid_fee, self.valid_currency) 38 self.assertTrue(item1.title is None) 39 self.assertTrue(item1.fee is None) 40 self.assertTrue(item1.currency is None) 41 self.assertEqual(item2.title, self.valid_title) 42 self.assertEqual(item2.fee, self.valid_fee) 43 self.assertEqual(item2.currency, self.valid_currency) 39 44 return 40 45 41 46 def test_illegal_value(self): 42 # we do not accept values not stored in IkobaUtils43 item = ResultEntry()47 # we do not accept values which do not meet the interface 48 item = ProductOptionEntry() 44 49 self.assertRaises( 45 ConstraintNotSatisfied, ResultEntry, 'invalid', 'invalid') 46 self.assertRaises( 47 ConstraintNotSatisfied, ResultEntry, 'invalid') 48 self.assertRaises( 49 ConstraintNotSatisfied, setattr, item, 'subject', 'blah') 50 self.assertRaises( 51 ConstraintNotSatisfied, setattr, item, 'grade', 'blah') 50 WrongType, ProductOptionEntry, 6, 500, 'invalid') 52 51 return 53 52 54 53 def test_to_string(self): 55 54 # the string representation is handy for export 56 item1 = ResultEntry() 57 item2 = ResultEntry(self.valid_subj, self.valid_grade) 58 self.assertEqual(item1.to_string(), u"(None, None)") 59 self.assertEqual(item2.to_string(), u"('%s', '%s')" % ( 60 self.valid_subj, self.valid_grade)) 55 item1 = ProductOptionEntry() 56 item2 = ProductOptionEntry( 57 self.valid_title, self.valid_fee, self.valid_currency) 58 self.assertEqual(item1.to_string(), u"(None, None, None)") 59 self.assertEqual(item2.to_string(), u"(u'%s', u'%s', u'%s')" % ( 60 self.valid_title, self.valid_fee, self.valid_currency)) 61 61 return 62 62 63 63 def test_from_string(self): 64 64 # we can create new result entries based on strings 65 myinput = u"(u'%s',u'%s')" % ( 66 self.valid_subj, self.valid_grade) 67 item1 = ResultEntry.from_string(myinput) 68 item2 = ResultEntry.from_string(u"(u'',u'')") 69 item3 = ResultEntry.from_string(u"(None, None)") 70 self.assertEqual(item1.subject, self.valid_subj) 71 self.assertEqual(item1.grade, self.valid_grade) 72 self.assertTrue(item2.subject is None) 73 self.assertTrue(item2.grade is None) 74 self.assertTrue(item3.subject is None) 75 self.assertTrue(item3.grade is None) 65 myinput = u"(u'%s',u'%s',u'%s')" % ( 66 self.valid_title, self.valid_fee, self.valid_currency) 67 item1 = ProductOptionEntry.from_string(myinput) 68 item2 = ProductOptionEntry.from_string(u"(u'', u'', u'')") 69 item3 = ProductOptionEntry.from_string(u"(None, None, None)") 70 self.assertEqual(item1.title, self.valid_title) 71 self.assertEqual(item1.fee, self.valid_fee) 72 self.assertEqual(item1.currency, self.valid_currency) 73 self.assertTrue(item2.title is None) 74 self.assertTrue(item2.fee is None) 75 self.assertEqual(item2.currency, None) 76 self.assertTrue(item3.title is None) 77 self.assertTrue(item3.fee is None) 78 self.assertEqual(item3.currency, None) 76 79 return 77 80 78 class ResultEntryFieldTests(unittest.TestCase):81 class ProductOptionEntryFieldTests(unittest.TestCase): 79 82 80 83 def test_ifaces(self): 81 84 # make sure we implement the promised interfaces. 82 obj = ResultEntryField()83 verifyObject(I ResultEntryField, obj)84 verifyClass(I ResultEntryField, ResultEntryField)85 obj = ProductOptionEntryField() 86 verifyObject(IProductOptionEntryField, obj) 87 verifyClass(IProductOptionEntryField, ProductOptionEntryField) 85 88 return 86 89 -
main/waeup.ikoba/trunk/src/waeup/ikoba/utils/converters.py
r12261 r12306 30 30 from zope.schema.interfaces import IList 31 31 from waeup.ikoba.interfaces import ( 32 IObjectConverter, I ResultEntryField, IFieldConverter, SubjectSource,33 GradeSource,DELETION_MARKER, IGNORE_MARKER)32 IObjectConverter, IProductOptionEntryField, IFieldConverter, 33 DELETION_MARKER, IGNORE_MARKER) 34 34 from waeup.ikoba.schema.interfaces import IPhoneNumber 35 from waeup.ikoba.schoolgrades import ResultEntry35 from waeup.ikoba.schoolgrades import ProductOptionEntry 36 36 37 37 class ExtendedCheckBoxWidget(CheckBoxWidget): … … 175 175 return result 176 176 177 class ResultEntryConverter(grok.Adapter):178 grok.context(I ResultEntryField)177 class ProductOptionEntryConverter(grok.Adapter): 178 grok.context(IProductOptionEntryField) 179 179 grok.implements(IFieldConverter) 180 180 181 181 def request_data(self, name, value, schema_field, prefix='', 182 182 mode='create'): 183 """Turn CSV values into ResultEntry-compatible form data.184 185 Expects as `value` a _string_ like ``(u'my subject',186 u'my grade')`` and turns it into some dict like::183 """Turn CSV values into ProductOptionEntry-compatible form data. 184 185 Expects as `value` a _string_ like ``(u'mytitle', 186 u'myfee')`` and turns it into some dict like:: 187 187 188 188 { 189 'form.grade.subject': u'9234896395...', 190 'form.grade.grade': u'7e67e9e777..' 189 'form.option.title': u'9234896395...', 190 'form.option.fee': 7698769 191 'form.option.currency': u'7e67e9e777..' 191 192 } 192 193 193 194 where the values are tokens from appropriate sources. 194 195 195 Such dicts can be transformed into real ResultEntry objects by196 Such dicts can be transformed into real ProductOptionEntry objects by 196 197 input widgets used in converters. 197 198 """ 198 199 try: 199 entry = ResultEntry.from_string(value)200 subj, grade = entry.subject, entry.grade200 entry = ProductOptionEntry.from_string(value) 201 title, fee, currency = entry.title, entry.fee, entry.currency 201 202 except: 202 203 return {prefix: value} 203 # web forms send tokens instead of real values204 s_token = SubjectSource().factory.getToken(subj)205 g_token = GradeSource().factory.getToken(grade)206 204 result = { 207 "%ssubject" % (prefix): s_token, 208 "%sgrade" % (prefix): g_token, 205 "%stitle" % (prefix): title, 206 "%sfee" % (prefix): fee, 207 "%scurrency" % (prefix): currency, 209 208 } 210 209 return result -
main/waeup.ikoba/trunk/src/waeup/ikoba/utils/tests/test_converters.py
r11954 r12306 23 23 import tempfile 24 24 import unittest 25 from decimal import Decimal 25 26 from zope import schema 26 27 from zope.component import provideUtility … … 35 36 from waeup.ikoba.testing import FunctionalLayer, FunctionalTestCase 36 37 from waeup.ikoba.interfaces import ( 37 SimpleIkobaVocabulary, SubjectSource, GradeSource,IFieldConverter,38 SimpleIkobaVocabulary, IFieldConverter, 38 39 DELETION_MARKER, IGNORE_MARKER) 39 from waeup.ikoba.schoolgrades import ResultEntryField40 from waeup.ikoba.schoolgrades import ProductOptionEntryField 40 41 from waeup.ikoba.utils.converters import ( 41 42 IObjectConverter, IFieldConverter, DefaultFieldConverter, 42 ListFieldConverter, PhoneNumberFieldConverter, ResultEntryConverter,43 ListFieldConverter, PhoneNumberFieldConverter, ProductOptionEntryConverter, 43 44 DefaultObjectConverter) 44 45 from waeup.ikoba.utils.helpers import attrs_to_fields … … 91 92 vocabulary = car_nums, 92 93 ) 93 grades = schema.List(94 title = u' School Grades',95 value_type = ResultEntryField(),94 options = schema.List( 95 title = u'Options', 96 value_type = ProductOptionEntryField(), 96 97 required = True, 97 98 default = [], … … 136 137 obj2 = ListFieldConverter(None) 137 138 obj3 = PhoneNumberFieldConverter(None) 138 obj4 = ResultEntryConverter(None)139 obj4 = ProductOptionEntryConverter(None) 139 140 verify.verifyObject(IFieldConverter, obj1) 140 141 verify.verifyObject(IFieldConverter, obj2) … … 144 145 verify.verifyClass(IFieldConverter, ListFieldConverter) 145 146 verify.verifyClass(IFieldConverter, PhoneNumberFieldConverter) 146 verify.verifyClass(IFieldConverter, ResultEntryConverter)147 verify.verifyClass(IFieldConverter, ProductOptionEntryConverter) 147 148 return 148 149 … … 384 385 return 385 386 386 def test_list_of_ resultentries(self):387 def test_list_of_optionentries(self): 387 388 # We can handle lists of result entries 388 389 converter = IObjectConverter(IContact) 389 390 # get currently valid values 390 s_src, g_src = SubjectSource(), GradeSource() 391 s_val1, s_val2 = list(s_src.factory.getValues())[0:2] 392 g_val1, g_val2 = list(g_src.factory.getValues())[0:2] 393 req_string = u"[('%s', '%s'), ('%s', '%s')]" % ( 394 s_val1, g_val1, s_val2, g_val2) 395 err, inv_err, data = converter.fromStringDict( 396 {"grades": req_string, 397 }, 398 'contact') 399 result_grades = data['grades'] 400 self.assertTrue(isinstance(result_grades, list)) 401 self.assertEqual(len(result_grades), 2) 402 self.assertEqual(result_grades[0].subject, s_val1) 403 self.assertEqual(result_grades[0].grade, g_val1) 391 req_string = u"[(u'T1', u'55.6', u'usd'), (u'T2', u'66.6', u'eur')]" 392 err, inv_err, data = converter.fromStringDict( 393 {"options": req_string,}, 'contact') 394 result_options = data['options'] 395 self.assertTrue(isinstance(result_options, list)) 396 self.assertEqual(len(result_options), 2) 397 self.assertEqual(result_options[0].title, 'T1') 398 self.assertEqual(result_options[0].fee, Decimal('55.6')) 399 self.assertEqual(result_options[0].currency, 'usd') 400 self.assertEqual(result_options[1].title, 'T2') 401 self.assertEqual(result_options[1].fee, Decimal('66.6')) 402 self.assertEqual(result_options[1].currency, 'eur') 404 403 return 405 404 … … 420 419 converter = IObjectConverter(IContact) 421 420 err, inv_err, data = converter.fromStringDict( 422 {" grades": DELETION_MARKER,421 {"options": DELETION_MARKER, 423 422 "friends": DELETION_MARKER}, 424 423 'contact', mode='update') 425 424 # grades are about to be set to default, friends to None 426 self.assertEqual(data, {' grades': [], 'friends': None})427 return 425 self.assertEqual(data, {'options': [], 'friends': None}) 426 return -
main/waeup.ikoba/trunk/src/waeup/ikoba/utils/utils.py
r12297 r12306 107 107 'no': 'no contract', 108 108 } 109 110 EXAM_SUBJECTS_DICT = {111 'math': 'Mathematics',112 'computer_science': 'Computer Science',113 }114 115 #: Exam grades. The tuple is sorted as it should be displayed in116 #: select boxes.117 EXAM_GRADES = (118 ('A', 'Best'),119 ('B', 'Better'),120 ('C', 'Good'),121 )122 109 123 110 PAYMENT_CATEGORIES = {
Note: See TracChangeset for help on using the changeset viewer.