def validateAction(self, data): # ActionExecutionError ... form wide error # WidgetActionExecutionError ... widget specific # TODO: validate all sort of extra info- new object does not exist yet # data contains already field values datasets = data.get('environmental_datasets', {}).keys() if not datasets: # FIXME: Make this a widget error, currently shown as form wide error raise ActionExecutionError(Invalid('No environmental dataset selected.')) # TODO: we should make sure only user picks only one option, otherwise pseudo absence # will be preferred (maybe we can do both?, select absence points, and fill up mith pseudo absences?) # we need an absence dataset or a a number of pseudo absence points if not data.get('species_pseudo_absence_points'): if not data.get('species_absence_dataset'): raise ActionExecutionError(RequiredMissing('No absence points selected.')) else: numabspoints = data.get('species_number_pseudo_absence_points') if not numabspoints: raise ActionExecutionError(RequiredMissing('No absence points selected')) elif numabspoints <= 0: raise ActionExecutionError(Invalid('Number of absence points must be greater than 0.')) # Determine lowest resolution # FIXME: this is slow and needs improvements # and accessing _terms is not ideal res_vocab = getUtility(IVocabularyFactory, 'resolution_source')(self.context) resolution_idx = -1 for dsbrain in (uuidToCatalogBrain(d) for d in datasets): idx = res_vocab._terms.index(res_vocab.getTerm(dsbrain.BCCResolution)) if idx > resolution_idx: resolution_idx = idx data['resolution'] = res_vocab._terms[resolution_idx].value
def _validate_fields(self, raw_data): errors = [] for name, field, schema in self.fields: if name not in raw_data: continue field = field.bind(self.obj or self.model) raw_value = raw_data.pop(name) if isinstance(raw_value, str): raw_value = raw_value.decode('utf8') # We don't want to accidentally swallow any adaptation TypeErrors from here: from_unicode = IFromUnicode(field) try: if raw_value in (None, u'', '') and field.required: raise RequiredMissing(name) try: value = from_unicode.fromUnicode(raw_value) except (ValueError, TypeError): raise WrongType(name) # TODO: make this more descriptive as to which validation failed, # where was it defined etc. except zope.schema.ValidationError as exc: errors.append((name, exc)) else: setattr(self.adapted_tmp_obj(self.tmp_obj, schema), name, value) return errors
def get_schema_validation_errors(action_data, schema): """Validate a dict against a schema. Return a list of basic schema validation errors (required fields, constraints, but doesn't check invariants yet). Loosely based on zope.schema.getSchemaValidationErrors, but: - Processes fields in schema order - Handles dict subscription access instead of object attribute access - Respects required / optional fields - Raises RequiredMissing instead of SchemaNotFullyImplemented """ errors = [] for name, field in getFieldsInOrder(schema): try: value = action_data[name] except KeyError: # property for the given name is not implemented if not field.required: continue errors.append((name, RequiredMissing(name))) else: try: field.bind(action_data).validate(value) except ValidationError as e: errors.append((name, e)) # Also reject fields that are not part of the schema errors.extend(get_unknown_fields(action_data, schema)) return errors
def test_validate_TestData(self): field = self.makeTestObject(schema=ITestSchema, required=False) data = self.makeTestData() field.validate(data) field = self.makeTestObject(schema=ITestSchema) field.validate(data) data.foo = None self.assertRaises(ValidationError, field.validate, data) self.assertRaises(WrongContainedType, field.validate, data) errors = self.getErrors(field.validate, data) self.assertEquals(errors[0], RequiredMissing('foo'))
def _marshall_from_json_data(self, value): """See `SimpleFieldMarshaller`.""" template = {} for name in self.field.schema.names(all=True): field = self.field.schema[name] if IField.providedBy(field): marshaller = getMultiAdapter( (field, self.request), IFieldMarshaller) if marshaller.representation_name in value: template[name] = marshaller.marshall_from_json_data( value[marshaller.representation_name]) elif field.required: raise RequiredMissing(name) return self.field.schema(template)
def __setitem__(self, key, value): key = self._validate(key) data = {} for name, field in getFieldsInOrder(self.schema): if name in self.omitted or field.readonly: continue attr = getattr(value, name, _marker) if attr is not _marker: data[name] = attr elif field.required and self.check: raise RequiredMissing(name) proxy = self.add(key) for name, attr in data.items(): setattr(proxy, name, attr)
def test_pm_AddEditDeleteAdvices(self): '''This test the MeetingItem.getAdvicesGroupsInfosForUser method. MeetingItem.getAdvicesGroupsInfosForUser returns 2 lists : first with addable advices and the second with editable/deletable advices.''' # creator for group 'developers' self.changeUser('pmCreator1') # create an item and ask the advice of group 'vendors' data = { 'title': 'Item to advice', 'category': 'maintenance' } item1 = self.create('MeetingItem', **data) item1.setOptionalAdvisers((self.vendors_uid, )) item1._update_after_edit() # 'pmCreator1' has no addable nor editable advice to give self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([], [])) self.changeUser('pmReviewer2') self.failIf(self.hasPermission(View, item1)) self.changeUser('pmCreator1') self.proposeItem(item1) # a user able to View the item can not add an advice, even if he tries... self.assertRaises(Unauthorized, createContentInContainer, item1, 'meetingadvice') self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([], [])) self.changeUser('pmReviewer2') # 'pmReviewer2' has one advice to give for 'vendors' and no advice to edit self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([(self.vendors_uid, u'Vendors')], [])) self.assertEquals(item1.hasAdvices(), False) # fields 'advice_type' and 'advice_group' are mandatory form = item1.restrictedTraverse('++add++meetingadvice').form_instance form.ti = self.portal.portal_types['meetingadvice'] self.request['PUBLISHED'] = form form.update() errors = form.extractData()[1] self.assertEquals(errors[0].error, RequiredMissing('advice_group')) self.assertEquals(errors[1].error, RequiredMissing('advice_type')) # value used for 'advice_type' and 'advice_group' must be correct form.request.set('form.widgets.advice_type', u'wrong_value') errors = form.extractData()[1] self.assertEquals(errors[1].error, RequiredMissing('advice_type')) # but if the value is correct, the field renders correctly form.request.set('form.widgets.advice_type', u'positive') data = form.extractData()[0] self.assertEquals(data['advice_type'], u'positive') # regarding 'advice_group' value, only correct are the ones in the vocabulary # so using another will fail, for example, can not give an advice for another group form.request.set('form.widgets.advice_group', self.developers_uid) data = form.extractData()[0] self.assertFalse('advice_group' in data) # we can use the values from the vocabulary vocab = form.widgets.get('advice_group').terms.terms self.failUnless(self.vendors_uid in vocab) self.assertEqual(len(vocab), 1) # give the advice, select a valid 'advice_group' and save form.request.set('form.widgets.advice_group', self.vendors_uid) # the 3 fields 'advice_group', 'advice_type' and 'advice_comment' are handled correctly data = form.extractData()[0] self.assertTrue('advice_group' in data and 'advice_type' in data and 'advice_comment' in data and 'advice_row_id' in data and 'advice_observations' in data and 'advice_hide_during_redaction' in data) # we receive the 6 fields self.assertEqual(len(data), len(form.fields)) form.request.form['advice_group'] = self.vendors_uid form.request.form['advice_type'] = u'positive' form.request.form['advice_comment'] = RichTextValue(u'My comment') form.createAndAdd(form.request.form) self.assertEquals(item1.hasAdvices(), True) # 'pmReviewer2' has no more addable advice (as already given) but has now an editable advice self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([], [(self.vendors_uid, 'Vendors')])) # given advice is correctly stored self.assertEquals(item1.adviceIndex[self.vendors_uid]['type'], 'positive') self.assertEquals(item1.adviceIndex[self.vendors_uid]['comment'], u'My comment') self.changeUser('pmReviewer1') self.validateItem(item1) # now 'pmReviewer2' can't add (already given) an advice # but he can still edit the advice he just gave self.changeUser('pmReviewer2') self.failUnless(self.hasPermission(View, item1)) self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([], [(self.vendors_uid, 'Vendors')])) given_advice = getattr(item1, item1.adviceIndex[self.vendors_uid]['advice_id']) self.failUnless(self.hasPermission(ModifyPortalContent, given_advice)) # another member of the same _advisers group may also edit the given advice self.changeUser('pmManager') self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([], [(self.vendors_uid, 'Vendors')])) self.failUnless(self.hasPermission(ModifyPortalContent, given_advice)) # if a user that can not remove the advice tries he gets Unauthorized self.changeUser('pmReviewer1') self.assertRaises(Unauthorized, item1.restrictedTraverse('@@delete_givenuid'), item1.meetingadvice.UID()) # put the item back in a state where 'pmReviewer2' can remove the advice self.changeUser('pmManager') self.backToState(item1, self._stateMappingFor('proposed')) self.changeUser('admin') # xxx NAmur, only admin can remove the advice item1.restrictedTraverse('@@delete_givenuid')(item1.meetingadvice.UID()) self.changeUser('pmReviewer2') self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([(self.vendors_uid, u'Vendors')], [])) # if advices are disabled in the meetingConfig, getAdvicesGroupsInfosForUser is emtpy self.changeUser('admin') self.meetingConfig.setUseAdvices(False) self.changeUser('pmReviewer2') self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([], [])) self.changeUser('admin') self.meetingConfig.setUseAdvices(True) # activate advices again and this time remove the fact that we asked the advice self.changeUser('pmReviewer2') self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([(self.vendors_uid, u'Vendors')], [])) self.changeUser('pmManager') item1.setOptionalAdvisers([]) item1._update_after_edit() self.changeUser('pmReviewer2') self.assertEquals(item1.getAdvicesGroupsInfosForUser(), ([], []))