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()
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')
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')
def test_get_one_item_back(self): data = Data({'a': 1, 'b': 2}, {}).normalized() result = utils.sift(data, ['b']) assert result == {0: ('b', 2)}
def test_no_required_items(self): data = Data({'a': 1, 'b': 2}, {}).normalized() result = utils.sift(data) assert result == {}
def test_get_one_item_back(self): data = Data({"a": 1, "b": 2}, {}).normalized() result = utils.sift(data, ["b"]) assert result == {0: ("b", 2)}
def test_no_required_items(self): data = Data({"a": 1, "b": 2}, {}).normalized() result = utils.sift(data) assert result == {}
def test_required_item_is_function_with_object(self): item = RequiredItem() item._object = 'a' data = Data({'a': 1, 'b': 2}, {}).normalized() result = utils.sift(data, [item]) assert result == {0: ('a', 1)}