예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
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'))
예제 #5
0
 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)
예제 #6
0
    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)
예제 #7
0
    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(), ([], []))