Exemplo n.º 1
0
    def traverser(self, data, schema, tree):
        """
        Traverses the dictionary, recursing onto itself if
        it sees appropriate key/value pairs that indicate that
        there is a need for more validation in a branch below us.
        """

        if hasattr(schema, '__validator_leaf__'):
            return schema(data, tree)

        if hasattr(schema, 'must_validate'):  # cherry picking?
            if not len(schema.must_validate):
                reason = "must_validate attribute must not be empty"
                raise SchemaError(data, tree, reason=reason)
            data = sift(data, schema.must_validate)

        schema = self.sanitize_optionals(data, schema, tree)

        for index in range(len(data)):
            self.length_equality(data, schema, index, tree)
            key, value = data[index]
            skey, svalue = schema[index]
            tree.append(key)

            # Validate the key before anything, to prevent recursing
            self.key_leaf(data[index], schema[index], tree)

            # If a dict is a value we need to recurse.
            # XXX Should we check isinstance(value, ndict) ?
            if isinstance(value, dict) and len(value):
                self.traverser(value, svalue, tree)
            else:
                self.value_leaf(data[index], schema[index], tree)
            if tree:
                tree.pop()
Exemplo n.º 2
0
    def enforce(self, data, schema, item_index, tree):
        # yo dawg, a recursive validator within a recursive validator anyone?
        if is_callable(schema) and hasattr(schema, '__validator_leaf__'):
            return schema(data[item_index], tree)
        if isinstance(data[item_index], dict) and isinstance(schema, tuple):
            try:
                _validator = Validator(data[item_index], schema)
                _validator.validate()
            except Invalid:
                e = sys.exc_info()[1]
                tree.append('list[%s]' % item_index)
                tree.extend(e.path)
                raise Invalid(e.schema_item,
                              tree,
                              reason=e._reason,
                              pair='value')

            # FIXME this is utterly redundant, and also happens in
            # RecursiveValidator
            except SchemaError:
                e = sys.exc_info()[1]
                tree.extend(e.path)
                raise SchemaError('', tree, reason=e._reason, pair='value')

        elif isinstance(schema,
                        tuple) and not isinstance(data[item_index],
                                                  (tuple, dict)):
            raise SchemaError(
                data,
                tree,
                reason='iterable contains single items, schema does not')
        else:
            try:
                if is_callable(schema):
                    schema(data[item_index])
                else:
                    ensure(data[item_index] == schema)
            except AssertionError:
                reason = sys.exc_info()[1]
                tree.append('list[%s]' % item_index)
                raise Invalid(schema, tree, reason=reason, pair='item')
Exemplo n.º 3
0
    def length_equality(self, data, schema, index, tree):
        try:
            data = data[index]
            try:
                schema = schema[index]
            except KeyError:
                if not hasattr(schema, 'must_validate'):
                    reason = 'has unexpected item in data: %s' % data_item(
                        data)
                    raise Invalid(None,
                                  tree,
                                  msg=reason,
                                  reason=reason,
                                  pair='value')
        except (KeyError, TypeError):
            if not hasattr(schema, 'must_validate'):
                reason = "has less items in schema than in data"
                raise SchemaError(data, tree, reason=reason)
        if hasattr(schema, '__validator_leaf__'):
            return

        if len(data) != len(schema):
            raise SchemaError(data, tree, reason='length did not match schema')
Exemplo n.º 4
0
    def is_alpha_ordered(self, data, normalized_schema, tree):
        keys = []
        indexes = normalized_schema.keys()
        for index in indexes:
            key = normalized_schema[index][0]
            if isinstance(key, str):
                keys.append(key)
            elif hasattr(key, '_object'):
                if isinstance(key._object, str):
                    keys.append(key._object)

        sorted_keys = sorted(keys)
        if keys != sorted_keys:
            for index, key in enumerate(keys):
                if key != sorted_keys[index]:
                    raise SchemaError(
                        keys, [key],
                        reason='schema item is not alphabetically ordered')
Exemplo n.º 5
0
 def enforce(self, data, schema, item_index, tree):
     # yo dawg, a recursive validator within a recursive validator anyone?
     if is_callable(schema) and hasattr(schema, '__validator_leaf__'):
         return schema(data, tree)
     try:
         _validate = Validator({}, self.schema)
         _validate.data = {0: data[item_index]}
         _validate.validate()
     except Invalid:
         e = sys.exc_info()[1]
         tree.extend(e.path)
         raise Invalid(e.schema_item,
                       tree,
                       pair='value',
                       msg=e._msg,
                       reason=e._reason)
     except SchemaError:
         e = sys.exc_info()[1]
         tree.extend(e.path)
         raise SchemaError('', tree, reason=e._reason, pair='value')
Exemplo n.º 6
0
 def traverser(self, data, schema, tree):
     if len(data) < self.index:
         reason = "has not enough items to select from"
         raise SchemaError(data, tree, reason=reason)
     self.leaves(data, schema, tree)
Exemplo n.º 7
0
    def traverser(self, data, schema, tree):
        """
        Traverses the dictionary, recursing onto itself if
        it sees appropriate key/value pairs that indicate that
        there is a need for more validation in a branch below us.
        """
        if hasattr(schema, '__validator_leaf__'):
            return schema(data, tree)

        if hasattr(schema, 'must_validate'):  # cherry picking?
            if not len(schema.must_validate):
                reason = "must_validate attribute must not be empty"
                raise SchemaError(data, tree, reason=reason)
            data = sift(data, schema.must_validate)

        schema = self.sanitize_optionals(data, schema, tree)

        validated_indexes = []
        skip_missing_indexes = getattr(schema, 'must_validate', False)

        if len(data) < len(schema):
            # we have missing required items in data, but we don't know
            # which ones so find what may fail:
            data_keys = [v[1] for v in data.values()]
            schema_keys = [v[1] for v in schema.values()]

            def enforce_once(data_keys, schema_key):
                # XXX Go through all the data keys and try and see if they pass
                # validation against the schema. At this point it is impossible
                # to know which data key corresponds to what schema key
                # (because schema keys can be a function/callable) so it is
                # a *very* naive way to try and detect which one might be
                # missing
                for data_key in data_keys:
                    failed = None
                    try:
                        enforce(data_key, schema_key, tree, pair='key')
                        return
                    except Invalid:
                        failed = data_key, schema_key

                    if failed:
                        return failed

            for schema_key in schema_keys:
                failure = enforce_once(data_keys, schema_key)
                if failure:
                    _, failed_schema_key = failure
                    msg = "required key in data is missing: %s" % str(
                        failed_schema_key)
                    raise Invalid(None, tree, reason=msg, pair='key')

        for index in range(len(data)):
            self.length_equality(data, schema, index, tree)
            key, value = data[index]
            skey, svalue = schema[index]
            tree.append(key)

            # Validate the key before anything, to prevent recursing
            self.key_leaf(data[index], schema[index], tree)

            # If a dict is a value we need to recurse.
            # XXX Should we check isinstance(value, ndict) ?
            if isinstance(value, dict) and len(value):
                self.traverser(value, svalue, tree)
            else:
                self.value_leaf(data[index], schema[index], tree)
            if tree:
                tree.pop()

            validated_indexes.append(index)

        # XXX There is a chance we might have missing items from
        # the incoming data that are labeled as required from the schema
        # we should make sure *here* that we account for that and raise
        # the appropriate exception. Since the loop finished and everything
        # seems to have passed, this lack of check will give false positives.
        missing_indexes = set(schema.keys()).difference(validated_indexes)
        if missing_indexes:
            if skip_missing_indexes:
                return
            for i in missing_indexes:
                if not hasattr(schema[i], 'is_optional'):
                    required_key = schema[i][0]
                    tree.append('item[%s]' % i)
                    msg = "required item in schema is missing: %s" % str(
                        required_key)
                    raise Invalid(required_key, tree, reason=msg, pair='key')