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)
        self.is_alpha_ordered(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[0] for v in data.values()]
            schema_keys = [v[0] 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

            # if there are no callables in the schema keys, just
            # find the missing data key directly
            if all([not is_callable(s) for s in schema_keys]):
                for schema_key in schema_keys:
                    if schema_key not in data_keys:
                        msg = "required key in data is missing: %s" % str(schema_key)
                        raise Invalid(None, tree, reason=msg, pair='key')

            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')
def traverser ( self , data , schema , tree ) : if hasattr ( schema , '__validator_leaf__' ) : return schema ( data , tree ) if hasattr ( schema , 'must_validate' ) : 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 ) self . is_alpha_ordered ( data , schema , tree ) validated_indexes = [ ] skip_missing_indexes = getattr ( schema , 'must_validate' , False ) if len ( data ) < len ( schema ) : data_keys = [ v [ 0 ] for v in data . values ( ) ] schema_keys = [ v [ 0 ] for v in schema . values ( ) ] def enforce_once ( data_keys , schema_key ) : 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 if all ( [ not is_callable ( s ) for s in schema_keys ] ) : for schema_key in schema_keys : if schema_key not in data_keys : msg = "required key in data is missing: %s" % str ( schema_key ) raise Invalid ( None , tree , reason = msg , pair = 'key' ) 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 ) self . key_leaf ( data [ index ] , schema [ index ] , tree ) 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 ) 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' )
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.