示例#1
0
def compareProperties(
    validator: jsonschema.Draft7Validator, compare: Dict, instance: Any, schema: Dict
) -> Iterator[jsonschema.ValidationError]:
    """
    compareProperties allows a schema to compare values in the instance against each other.
    Amazingly, json-schema does not have a built-in way to do this.

    Example: ensuring that hyperparmeter minval is less than maxval:

        "compareProperties": {
            "type": "a<b",
            "a": "minval",
            "b": "maxval"
        }
    """
    if not validator.is_type(instance, "object"):
        return

    def get_by_path(path: str) -> Any:
        obj = instance
        for key in path.split("."):
            if not obj:
                return None
            obj = obj.get(key)
        return obj

    a_path = compare["a"]
    a = get_by_path(a_path)

    b_path = compare["b"]
    b = get_by_path(b_path)

    if a is None or b is None:
        return

    typ = compare["type"]

    if typ == "a<b":
        if a >= b:
            yield jsonschema.ValidationError(f"{a_path} must be less than {b_path}")
        return

    if typ == "a<=b":
        if a > b:
            yield jsonschema.ValidationError(f"{a_path} must be less than {b_path}")
        return

    if typ == "a_is_subdir_of_b":
        a_norm = os.path.normpath(a)
        b_norm = os.path.normpath(b)
        if os.path.isabs(a_norm):
            if not a_norm.startswith(b_norm):
                yield jsonschema.ValidationError(f"{a_path} must be a subdirectory of {b_path}")
        else:
            if a_norm.startswith(".."):
                yield jsonschema.ValidationError(f"{a_path} must be a subdirectory of {b_path}")
        return

    raise ValueError(f"unrecognized comparison {compare[typ]}")
示例#2
0
文件: util.py 项目: onecommons/unfurl
    def set_defaults(validator: Draft7Validator, properties: Mapping,
                     instance: Draft7Validator,
                     schema: Mapping) -> Union[Generator, Draft7Validator]:
        if not validator.is_type(instance, "object"):
            return

        for key, subschema in properties.items():
            if "default" in subschema:
                instance.setdefault(key, subschema["default"])

        for error in validate_properties(validator, properties, instance,
                                         schema):
            yield error
示例#3
0
def disallowProperties(
    validator: jsonschema.Draft7Validator, disallowed: Dict, instance: Any, schema: Dict
) -> Iterator[jsonschema.ValidationError]:
    """
    disallowProperties is for restricting which properties are allowed in an object with
    per-property, such as when we allow a k8s pod spec with some fields disallowed.

    Example: The "pod_spec" property of the environment config:

        "pod_spec": {
            "type": "object",
            "disallowProperties": {
                "name": "pod Name is not a configurable option",
                "name_space": "pod NameSpace is not a configurable option"
            }
        }
    """
    if not validator.is_type(instance, "object"):
        return

    for prop in instance:
        if prop in disallowed:
            msg = disallowed[prop]
            yield jsonschema.ValidationError(msg)
示例#4
0
def compareProperties(validator: jsonschema.Draft7Validator, compare: Dict,
                      instance: Any,
                      schema: Dict) -> Iterator[jsonschema.ValidationError]:
    """
    compareProperties allows a schema to compare values in the instance against each other.
    Amazingly, json-schema does not have a built-in way to do this.

    Example: ensuring that hyperparmeter minval is less than maxval:

        "compareProperties": {
            "type": "a<b",
            "a": "minval",
            "b": "maxval"
        }
    """
    if not validator.is_type(instance, "object"):
        return

    def get_by_path(path: str) -> Any:
        obj = instance
        for key in path.split("."):
            if not obj:
                return None
            obj = obj.get(key)
        return obj

    a_path = compare["a"]
    a = get_by_path(a_path)

    b_path = compare["b"]
    b = get_by_path(b_path)

    if a is None or b is None:
        return

    typ = compare["type"]

    if typ == "a<b":
        if a >= b:
            yield jsonschema.ValidationError(
                f"{a_path} must be less than {b_path}")
        return

    if typ == "same_units":
        # same_units refers to a Length object.
        if not isinstance(a, dict) or not isinstance(b, dict):
            return
        if next(iter(a.keys())) != next(iter(b.keys())):
            yield jsonschema.ValidationError(
                f"{a_path} must be defined in the same units as {b_path}")
        return

    if typ == "length_a<length_b":
        # length_a<length_b compares two length objects.
        if not isinstance(a, dict) or not isinstance(b, dict):
            return
        # Assume the same units.
        length_a = next(iter(a.values()))
        length_b = next(iter(b.values()))
        if not isinstance(length_a, int) or not isinstance(length_b, int):
            return
        if length_a >= length_b:
            yield jsonschema.ValidationError(
                f"{a_path} must be less than {b_path}")
        return

    if typ == "a_is_subdir_of_b":
        a_norm = os.path.normpath(a)
        b_norm = os.path.normpath(b)
        if os.path.isabs(a_norm):
            if not a_norm.startswith(b_norm):
                yield jsonschema.ValidationError(
                    f"{a_path} must be a subdirectory of {b_path}")
        else:
            if a_norm.startswith(".."):
                yield jsonschema.ValidationError(
                    f"{a_path} must be a subdirectory of {b_path}")
        return

    raise ValueError(f"unrecognized comparison {compare[typ]}")