Changeset 79:54aa7dd5fe81 for wokkel
- Timestamp:
- Jan 5, 2010, 2:53:43 PM (12 years ago)
- Branch:
- default
- Location:
- wokkel
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
wokkel/data_form.py
r78 r79 76 76 option['label'] = self.label 77 77 return option 78 78 79 79 80 @staticmethod … … 213 214 if self.values: 214 215 if (self.fieldType not in ('hidden', 'jid-multi', 'list-multi', 215 'text-multi') and216 'text-multi', None) and 216 217 len(self.values) > 1): 217 218 raise TooManyValuesError() … … 234 235 self.values = newValues 235 236 237 236 238 def toElement(self, asForm=False): 237 239 """ … … 245 247 field = domish.Element((NS_X_DATA, 'field')) 246 248 247 if asForm or self.fieldType != 'text-single':249 if self.fieldType: 248 250 field['type'] = self.fieldType 249 251 … … 323 325 324 326 @staticmethod 325 def fromDict(dictionary): 326 kwargs = dictionary.copy() 327 328 if 'type' in dictionary: 329 kwargs['fieldType'] = dictionary['type'] 327 def fromDict(fieldDict): 328 """ 329 Create a field from a dictionary. 330 331 This is a short hand for passing arguments directly on Field object 332 creation. The field type is represented by the C{'type'} key. For 333 C{'options'} the value is not a list of L{Option}s, but a dictionary 334 keyed by value, with an optional label as value. 335 """ 336 kwargs = fieldDict.copy() 337 338 if 'type' in fieldDict: 339 kwargs['fieldType'] = fieldDict['type'] 330 340 del kwargs['type'] 331 341 332 if 'options' in dictionary:342 if 'options' in fieldDict: 333 343 options = [] 334 for value, label in dictionary['options'].iteritems():344 for value, label in fieldDict['options'].iteritems(): 335 345 options.append(Option(value, label)) 336 346 kwargs['options'] = options … … 416 426 Add a field to this form. 417 427 418 Fields are added in order, and L{fields} is a dictionary of the428 Fields are added in order, and C{fields} is a dictionary of the 419 429 named fields, that is kept in sync only if this method is used for 420 430 adding new fields. Multiple fields with the same name are disallowed. … … 429 439 430 440 441 def removeField(self, field): 442 """ 443 Remove a field from this form. 444 """ 445 self.fieldList.remove(field) 446 447 if field.var is not None: 448 del self.fields[field.var] 449 450 451 def makeFields(self, values, fieldDefs=None, filterUnknown=True): 452 """ 453 Create fields from values and add them to this form. 454 455 This creates fields from a mapping of name to value(s) and adds them to 456 this form. It is typically used for generating outgoing forms. 457 458 If C{fieldDefs} is not C{None}, this is used to fill in 459 additional properties of fields, like the field types, labels and 460 possible options. 461 462 If C{filterUnknown} is C{True} and C{fieldDefs} is not C{None}, fields 463 will only be created from C{values} with a corresponding entry in 464 C{fieldDefs}. 465 466 If the field type is unknown, the field type is C{None}. When the form 467 is rendered using L{toElement}, these fields will have no C{'type'} 468 attribute, and it is up to the receiving party to interpret the values 469 properly (e.g. by knowing about the FORM_TYPE in L{formNamespace} and 470 the field name). 471 472 @param values: Values to create fields from. 473 @type values: C{dict} 474 475 @param fieldDefs: Field definitions as a dictionary. See 476 L{wokkel.iwokkel.IPubSubService.getConfigurationOptions} 477 @type fieldDefs: C{dict} 478 479 @param filterUnknown: If C{True}, ignore fields that are not in 480 C{fieldDefs}. 481 @type filterUnknown: C{bool} 482 """ 483 for name, value in values.iteritems(): 484 fieldDict = {'var': name, 485 'type': None} 486 487 if fieldDefs is not None: 488 if name in fieldDefs: 489 fieldDict.update(fieldDefs[name]) 490 elif filterUnknown: 491 continue 492 493 if isinstance(value, list): 494 fieldDict['values'] = value 495 else: 496 fieldDict['value'] = value 497 498 self.addField(Field.fromDict(fieldDict)) 499 500 431 501 def toElement(self): 502 """ 503 Return the DOM representation of this Form. 504 505 @rtype: L{domish.Element} 506 """ 432 507 form = domish.Element((NS_X_DATA, 'x')) 433 508 form['type'] = self.formType … … 517 592 518 593 return values 594 595 596 def typeCheck(self, fieldDefs=None, filterUnknown=False): 597 """ 598 Check values of fields according to the field definition. 599 600 This method walks all named fields to check their values against their 601 type, and is typically used for forms received from other entities. The 602 field definition in C{fieldDefs} is used to check the field type. 603 604 If C{filterUnknown} is C{True}, fields that are not present in 605 C{fieldDefs} are removed from the form. 606 607 If the field type is C{None} (when not set by the sending entity), 608 the type from the field definitition is used, or C{'text-single'} if 609 that is not set. 610 611 If C{fieldDefs} is None, an empty dictionary is assumed. This is 612 useful for coercing boolean and JID values on forms with type 613 C{'form'}. 614 615 @param fieldDefs: Field definitions as a dictionary. See 616 L{wokkel.iwokkel.IPubSubService.getConfigurationOptions} 617 @type fieldDefs: C{dict} 618 619 @param filterUnknown: If C{True}, remove fields that are not in 620 C{fieldDefs}. 621 @type filterUnknown: C{bool} 622 """ 623 624 if fieldDefs is None: 625 fieldDefs = {} 626 627 filtered = [] 628 629 for name, field in self.fields.iteritems(): 630 if name in fieldDefs: 631 fieldDef = fieldDefs[name] 632 if 'type' not in fieldDef: 633 fieldDef['type'] = 'text-single' 634 635 if field.fieldType is None: 636 field.fieldType = fieldDef['type'] 637 elif field.fieldType != fieldDef['type']: 638 raise TypeError("Field type for %r is %r, expected %r" % 639 (name, 640 field.fieldType, 641 fieldDef['type'])) 642 else: 643 # Field type is correct 644 pass 645 field.typeCheck() 646 elif filterUnknown: 647 filtered.append(field) 648 elif field.fieldType is not None: 649 field.typeCheck() 650 else: 651 # Unknown field without type, no checking, no filtering 652 pass 653 654 for field in filtered: 655 self.removeField(field) -
wokkel/pubsub.py
r63 r79 1 1 # -*- test-case-name: wokkel.test.test_pubsub -*- 2 2 # 3 # Copyright (c) 2003-20 09Ralph Meijer3 # Copyright (c) 2003-2010 Ralph Meijer 4 4 # See LICENSE for details. 5 5 … … 1013 1013 1014 1014 1015 def _makeFields(self, options, values):1016 fields = []1017 for name, value in values.iteritems():1018 if name not in options:1019 continue1020 1021 option = {'var': name}1022 option.update(options[name])1023 if isinstance(value, list):1024 option['values'] = value1025 else:1026 option['value'] = value1027 fields.append(data_form.Field.fromDict(option))1028 return fields1029 1030 1031 1015 def _formFromConfiguration(self, resource, values): 1032 options = resource.getConfigurationOptions() 1033 fields = self._makeFields(options, values) 1016 fieldDefs = resource.getConfigurationOptions() 1034 1017 form = data_form.Form(formType="form", 1035 formNamespace=NS_PUBSUB_NODE_CONFIG, 1036 fields=fields) 1037 1018 formNamespace=NS_PUBSUB_NODE_CONFIG) 1019 form.makeFields(values, fieldDefs) 1038 1020 return form 1039 1021 -
wokkel/test/test_data_form.py
r78 r79 135 135 136 136 137 def test_toElementTypeNot ListSingle(self):138 """ 139 Always render the field type, if different from list-single.137 def test_toElementTypeNotTextSingle(self): 138 """ 139 Always render the field type, if different from text-single. 140 140 """ 141 141 field = data_form.Field('hidden', var='test') … … 143 143 144 144 self.assertEquals('hidden', element.getAttribute('type')) 145 146 147 def test_toElementSingleValue(self): 148 """ 149 A single value should yield only one value element. 150 """ 151 field = data_form.Field('list-multi', var='test', value='test') 152 element = field.toElement() 153 154 children = list(element.elements()) 155 self.assertEqual(1, len(children)) 156 157 158 def test_toElementMultipleValues(self): 159 """ 160 A field with no type and multiple values should render all values. 161 """ 162 field = data_form.Field('list-multi', var='test', 163 values=['test', 'test2']) 164 element = field.toElement() 165 166 children = list(element.elements()) 167 self.assertEqual(2, len(children)) 145 168 146 169 … … 241 264 element = field.toElement() 242 265 self.assertEqual(u'true', unicode(element.value)) 266 267 268 def test_toElementNoType(self): 269 """ 270 A field with no type should not have a type attribute. 271 """ 272 field = data_form.Field(None, var='test', value='test') 273 element = field.toElement() 274 self.assertFalse(element.hasAttribute('type')) 275 276 277 def test_toElementNoTypeMultipleValues(self): 278 """ 279 A field with no type and multiple values should render all values. 280 """ 281 field = data_form.Field(None, var='test', values=['test', 'test2']) 282 element = field.toElement() 283 284 self.assertFalse(element.hasAttribute('type')) 285 children = list(element.elements()) 286 self.assertEqual(2, len(children)) 243 287 244 288 … … 788 832 789 833 834 def test_removeField(self): 835 """ 836 A removed field should not occur in fieldList. 837 """ 838 form = data_form.Form('result') 839 field = data_form.Field('fixed', value='Section 1') 840 form.addField(field) 841 form.removeField(field) 842 self.assertNotIn(field, form.fieldList) 843 844 845 def test_removeFieldNamed(self): 846 """ 847 A removed named field should not occur in fields. 848 """ 849 form = data_form.Form('result') 850 field = data_form.Field(var='test', value='test1') 851 form.addField(field) 852 form.removeField(field) 853 self.assertNotIn('test', form.fields) 854 855 856 def test_makeField(self): 857 """ 858 Fields can be created from a dict of values and a dict of field defs. 859 """ 860 fieldDefs = { 861 "pubsub#persist_items": 862 {"type": "boolean", 863 "label": "Persist items to storage"}, 864 "pubsub#deliver_payloads": 865 {"type": "boolean", 866 "label": "Deliver payloads with event notifications"}, 867 "pubsub#creator": 868 {"type": "jid-single", 869 "label": "The JID of the node creator"}, 870 "pubsub#description": 871 {"type": "text-single", 872 "label": "A description of the node"}, 873 "pubsub#owner": 874 {"type": "jid-single", 875 "label": "Owner of the node"}, 876 } 877 values = {'pubsub#deliver_payloads': '0', 878 'pubsub#persist_items': True, 879 'pubsub#description': 'a great node', 880 'pubsub#owner': jid.JID('user@example.org'), 881 'x-myfield': ['a', 'b']} 882 883 form = data_form.Form('submit') 884 form.makeFields(values, fieldDefs) 885 886 # Check that the expected fields have been created 887 self.assertIn('pubsub#deliver_payloads', form.fields) 888 self.assertIn('pubsub#persist_items', form.fields) 889 self.assertIn('pubsub#description', form.fields) 890 self.assertIn('pubsub#owner', form.fields) 891 892 # This field is not created because there is no value for it. 893 self.assertNotIn('pubsub#creator', form.fields) 894 895 # This field is not created because it does not appear in fieldDefs 896 # and filterUnknown defaults to True 897 self.assertNotIn('x-myfield', form.fields) 898 899 # Check properties the created fields 900 self.assertEqual('boolean', 901 form.fields['pubsub#deliver_payloads'].fieldType) 902 self.assertEqual('0', 903 form.fields['pubsub#deliver_payloads'].value) 904 self.assertEqual('Deliver payloads with event notifications', 905 form.fields['pubsub#deliver_payloads'].label) 906 self.assertEqual(True, 907 form.fields['pubsub#persist_items'].value) 908 909 910 def test_makeFieldNotFilterUnknown(self): 911 """ 912 Fields can be created from a dict of values and a dict of field defs. 913 """ 914 fieldDefs = { 915 "pubsub#persist_items": 916 {"type": "boolean", 917 "label": "Persist items to storage"}, 918 } 919 values = {'x-myfield': ['a', 'b']} 920 921 form = data_form.Form('submit') 922 form.makeFields(values, fieldDefs, filterUnknown=False) 923 924 field = form.fields['x-myfield'] 925 self.assertEqual(None, field.fieldType) 926 self.assertEqual(values, form.getValues()) 927 928 929 def test_makeFieldsUnknownTypeJID(self): 930 """ 931 Without type, a single JID value sets field type jid-single. 932 """ 933 values = {'pubsub#creator': jid.JID('user@example.org')} 934 form = data_form.Form('result') 935 form.makeFields(values) 936 937 field = form.fields['pubsub#creator'] 938 self.assertEqual(None, field.fieldType) 939 self.assertEqual(values, form.getValues()) 940 941 942 def test_makeFieldsUnknownTypeJIDMulti(self): 943 """ 944 Without type, multiple JID values sets field type jid-multi. 945 """ 946 values = {'pubsub#contact': [jid.JID('user@example.org'), 947 jid.JID('other@example.org')]} 948 form = data_form.Form('result') 949 form.makeFields(values) 950 951 field = form.fields['pubsub#contact'] 952 self.assertEqual(None, field.fieldType) 953 self.assertEqual(values, form.getValues()) 954 955 956 def test_makeFieldsUnknownTypeBoolean(self): 957 """ 958 Without type, a boolean value sets field type boolean. 959 """ 960 values = {'pubsub#persist_items': True} 961 form = data_form.Form('result') 962 form.makeFields(values) 963 964 field = form.fields['pubsub#persist_items'] 965 self.assertEqual(None, field.fieldType) 966 self.assertEqual(values, form.getValues()) 967 968 969 def test_makeFieldsUnknownTypeListMulti(self): 970 """ 971 Without type, multiple values sets field type list-multi. 972 """ 973 values = {'pubsub#show-values': ['chat', 'online', 'away']} 974 form = data_form.Form('result') 975 form.makeFields(values) 976 977 field = form.fields['pubsub#show-values'] 978 self.assertEqual(None, field.fieldType) 979 self.assertEqual(values, form.getValues()) 980 981 790 982 def test_getValues(self): 791 983 """ … … 835 1027 values = form.getValues() 836 1028 self.assertEqual({'features': 'news'}, values) 1029 1030 1031 def test_typeCheckKnownFieldChecked(self): 1032 """ 1033 Known fields are type checked. 1034 """ 1035 checked = [] 1036 fieldDefs = {"pubsub#description": 1037 {"type": "text-single", 1038 "label": "A description of the node"}} 1039 form = data_form.Form('submit') 1040 form.addField(data_form.Field(var='pubsub#description', 1041 value='a node')) 1042 field = form.fields['pubsub#description'] 1043 field.typeCheck = lambda : checked.append(None) 1044 form.typeCheck(fieldDefs) 1045 1046 self.assertEqual([None], checked) 1047 1048 1049 def test_typeCheckKnownFieldNoType(self): 1050 """ 1051 Known fields without a type get the type of the field definition. 1052 """ 1053 checked = [] 1054 fieldDefs = {"pubsub#description": 1055 {"type": "text-single", 1056 "label": "A description of the node"}} 1057 form = data_form.Form('submit') 1058 form.addField(data_form.Field(None, var='pubsub#description', 1059 value='a node')) 1060 field = form.fields['pubsub#description'] 1061 field.typeCheck = lambda : checked.append(None) 1062 form.typeCheck(fieldDefs) 1063 1064 self.assertEqual('text-single', field.fieldType) 1065 self.assertEqual([None], checked) 1066 1067 1068 def test_typeCheckWrongFieldType(self): 1069 """ 1070 A field should have the same type as the field definition. 1071 """ 1072 checked = [] 1073 fieldDefs = {"pubsub#description": 1074 {"type": "text-single", 1075 "label": "A description of the node"}} 1076 form = data_form.Form('submit') 1077 form.addField(data_form.Field('list-single', var='pubsub#description', 1078 value='a node')) 1079 field = form.fields['pubsub#description'] 1080 field.typeCheck = lambda : checked.append(None) 1081 1082 self.assertRaises(TypeError, form.typeCheck, fieldDefs) 1083 self.assertEqual([], checked) 1084 1085 1086 def test_typeCheckDefaultTextSingle(self): 1087 """ 1088 If a field definition has no type, use text-single. 1089 """ 1090 checked = [] 1091 fieldDefs = {"pubsub#description": 1092 {"label": "A description of the node"}} 1093 form = data_form.Form('submit') 1094 form.addField(data_form.Field('text-single', var='pubsub#description', 1095 value='a node')) 1096 field = form.fields['pubsub#description'] 1097 field.typeCheck = lambda : checked.append(None) 1098 form.typeCheck(fieldDefs) 1099 1100 self.assertEqual([None], checked) 1101 1102 1103 def test_typeCheckUnknown(self): 1104 """ 1105 Unknown fields are checked, not removed if filterUnknown False. 1106 """ 1107 checked = [] 1108 fieldDefs = {} 1109 form = data_form.Form('submit') 1110 form.addField(data_form.Field('list-single', var='pubsub#description', 1111 value='a node')) 1112 field = form.fields['pubsub#description'] 1113 field.typeCheck = lambda : checked.append(None) 1114 form.typeCheck(fieldDefs, filterUnknown=False) 1115 1116 self.assertIn('pubsub#description', form.fields) 1117 self.assertEqual([None], checked) 1118 1119 1120 def test_typeCheckUnknownNoType(self): 1121 """ 1122 Unknown fields without type are not checked. 1123 """ 1124 checked = [] 1125 fieldDefs = {} 1126 form = data_form.Form('submit') 1127 form.addField(data_form.Field(None, var='pubsub#description', 1128 value='a node')) 1129 field = form.fields['pubsub#description'] 1130 field.typeCheck = lambda : checked.append(None) 1131 form.typeCheck(fieldDefs, filterUnknown=False) 1132 1133 self.assertIn('pubsub#description', form.fields) 1134 self.assertEqual([], checked) 1135 1136 1137 def test_typeCheckUnknownRemoved(self): 1138 """ 1139 Unknown fields are not checked, and removed if filterUnknown True. 1140 """ 1141 checked = [] 1142 fieldDefs = {} 1143 form = data_form.Form('submit') 1144 form.addField(data_form.Field('list-single', var='pubsub#description', 1145 value='a node')) 1146 field = form.fields['pubsub#description'] 1147 field.typeCheck = lambda : checked.append(None) 1148 form.typeCheck(fieldDefs, filterUnknown=True) 1149 1150 self.assertNotIn('pubsub#description', form.fields) 1151 self.assertEqual([], checked) 1152 1153 1154 def test_typeCheckNoFieldDefs(self): 1155 """ 1156 If there are no field defs, an empty dictionary is assumed. 1157 """ 1158 checked = [] 1159 form = data_form.Form('submit') 1160 form.addField(data_form.Field('list-single', var='pubsub#description', 1161 value='a node')) 1162 field = form.fields['pubsub#description'] 1163 field.typeCheck = lambda : checked.append(None) 1164 form.typeCheck() 1165 1166 self.assertIn('pubsub#description', form.fields) 1167 self.assertEqual([None], checked)
Note: See TracChangeset
for help on using the changeset viewer.