about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/jsonschema/_utils.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/jsonschema/_utils.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/jsonschema/_utils.py')
-rw-r--r--.venv/lib/python3.12/site-packages/jsonschema/_utils.py351
1 files changed, 351 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/jsonschema/_utils.py b/.venv/lib/python3.12/site-packages/jsonschema/_utils.py
new file mode 100644
index 00000000..54d28c04
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/jsonschema/_utils.py
@@ -0,0 +1,351 @@
+from collections.abc import Mapping, MutableMapping, Sequence
+from urllib.parse import urlsplit
+import itertools
+import re
+
+
+class URIDict(MutableMapping):
+    """
+    Dictionary which uses normalized URIs as keys.
+    """
+
+    def normalize(self, uri):
+        return urlsplit(uri).geturl()
+
+    def __init__(self, *args, **kwargs):
+        self.store = dict()
+        self.store.update(*args, **kwargs)
+
+    def __getitem__(self, uri):
+        return self.store[self.normalize(uri)]
+
+    def __setitem__(self, uri, value):
+        self.store[self.normalize(uri)] = value
+
+    def __delitem__(self, uri):
+        del self.store[self.normalize(uri)]
+
+    def __iter__(self):
+        return iter(self.store)
+
+    def __len__(self):  # pragma: no cover -- untested, but to be removed
+        return len(self.store)
+
+    def __repr__(self):  # pragma: no cover -- untested, but to be removed
+        return repr(self.store)
+
+
+class Unset:
+    """
+    An as-of-yet unset attribute or unprovided default parameter.
+    """
+
+    def __repr__(self):  # pragma: no cover
+        return "<unset>"
+
+
+def format_as_index(container, indices):
+    """
+    Construct a single string containing indexing operations for the indices.
+
+    For example for a container ``bar``, [1, 2, "foo"] -> bar[1][2]["foo"]
+
+    Arguments:
+
+        container (str):
+
+            A word to use for the thing being indexed
+
+        indices (sequence):
+
+            The indices to format.
+
+    """
+    if not indices:
+        return container
+    return f"{container}[{']['.join(repr(index) for index in indices)}]"
+
+
+def find_additional_properties(instance, schema):
+    """
+    Return the set of additional properties for the given ``instance``.
+
+    Weeds out properties that should have been validated by ``properties`` and
+    / or ``patternProperties``.
+
+    Assumes ``instance`` is dict-like already.
+    """
+    properties = schema.get("properties", {})
+    patterns = "|".join(schema.get("patternProperties", {}))
+    for property in instance:
+        if property not in properties:
+            if patterns and re.search(patterns, property):
+                continue
+            yield property
+
+
+def extras_msg(extras):
+    """
+    Create an error message for extra items or properties.
+    """
+    verb = "was" if len(extras) == 1 else "were"
+    return ", ".join(repr(extra) for extra in extras), verb
+
+
+def ensure_list(thing):
+    """
+    Wrap ``thing`` in a list if it's a single str.
+
+    Otherwise, return it unchanged.
+    """
+    if isinstance(thing, str):
+        return [thing]
+    return thing
+
+
+def _mapping_equal(one, two):
+    """
+    Check if two mappings are equal using the semantics of `equal`.
+    """
+    if len(one) != len(two):
+        return False
+    return all(
+        key in two and equal(value, two[key])
+        for key, value in one.items()
+    )
+
+
+def _sequence_equal(one, two):
+    """
+    Check if two sequences are equal using the semantics of `equal`.
+    """
+    if len(one) != len(two):
+        return False
+    return all(equal(i, j) for i, j in zip(one, two))
+
+
+def equal(one, two):
+    """
+    Check if two things are equal evading some Python type hierarchy semantics.
+
+    Specifically in JSON Schema, evade `bool` inheriting from `int`,
+    recursing into sequences to do the same.
+    """
+    if one is two:
+        return True
+    if isinstance(one, str) or isinstance(two, str):
+        return one == two
+    if isinstance(one, Sequence) and isinstance(two, Sequence):
+        return _sequence_equal(one, two)
+    if isinstance(one, Mapping) and isinstance(two, Mapping):
+        return _mapping_equal(one, two)
+    return unbool(one) == unbool(two)
+
+
+def unbool(element, true=object(), false=object()):
+    """
+    A hack to make True and 1 and False and 0 unique for ``uniq``.
+    """
+    if element is True:
+        return true
+    elif element is False:
+        return false
+    return element
+
+
+def uniq(container):
+    """
+    Check if all of a container's elements are unique.
+
+    Tries to rely on the container being recursively sortable, or otherwise
+    falls back on (slow) brute force.
+    """
+    try:
+        sort = sorted(unbool(i) for i in container)
+        sliced = itertools.islice(sort, 1, None)
+
+        for i, j in zip(sort, sliced):
+            if equal(i, j):
+                return False
+
+    except (NotImplementedError, TypeError):
+        seen = []
+        for e in container:
+            e = unbool(e)
+
+            for i in seen:
+                if equal(i, e):
+                    return False
+
+            seen.append(e)
+    return True
+
+
+def find_evaluated_item_indexes_by_schema(validator, instance, schema):
+    """
+    Get all indexes of items that get evaluated under the current schema.
+
+    Covers all keywords related to unevaluatedItems: items, prefixItems, if,
+    then, else, contains, unevaluatedItems, allOf, oneOf, anyOf
+    """
+    if validator.is_type(schema, "boolean"):
+        return []
+    evaluated_indexes = []
+
+    if "items" in schema:
+        return list(range(len(instance)))
+
+    ref = schema.get("$ref")
+    if ref is not None:
+        resolved = validator._resolver.lookup(ref)
+        evaluated_indexes.extend(
+            find_evaluated_item_indexes_by_schema(
+                validator.evolve(
+                    schema=resolved.contents,
+                    _resolver=resolved.resolver,
+                ),
+                instance,
+                resolved.contents,
+            ),
+        )
+
+    dynamicRef = schema.get("$dynamicRef")
+    if dynamicRef is not None:
+        resolved = validator._resolver.lookup(dynamicRef)
+        evaluated_indexes.extend(
+            find_evaluated_item_indexes_by_schema(
+                validator.evolve(
+                    schema=resolved.contents,
+                    _resolver=resolved.resolver,
+                ),
+                instance,
+                resolved.contents,
+            ),
+        )
+
+    if "prefixItems" in schema:
+        evaluated_indexes += list(range(len(schema["prefixItems"])))
+
+    if "if" in schema:
+        if validator.evolve(schema=schema["if"]).is_valid(instance):
+            evaluated_indexes += find_evaluated_item_indexes_by_schema(
+                validator, instance, schema["if"],
+            )
+            if "then" in schema:
+                evaluated_indexes += find_evaluated_item_indexes_by_schema(
+                    validator, instance, schema["then"],
+                )
+        elif "else" in schema:
+            evaluated_indexes += find_evaluated_item_indexes_by_schema(
+                validator, instance, schema["else"],
+            )
+
+    for keyword in ["contains", "unevaluatedItems"]:
+        if keyword in schema:
+            for k, v in enumerate(instance):
+                if validator.evolve(schema=schema[keyword]).is_valid(v):
+                    evaluated_indexes.append(k)
+
+    for keyword in ["allOf", "oneOf", "anyOf"]:
+        if keyword in schema:
+            for subschema in schema[keyword]:
+                errs = next(validator.descend(instance, subschema), None)
+                if errs is None:
+                    evaluated_indexes += find_evaluated_item_indexes_by_schema(
+                        validator, instance, subschema,
+                    )
+
+    return evaluated_indexes
+
+
+def find_evaluated_property_keys_by_schema(validator, instance, schema):
+    """
+    Get all keys of items that get evaluated under the current schema.
+
+    Covers all keywords related to unevaluatedProperties: properties,
+    additionalProperties, unevaluatedProperties, patternProperties,
+    dependentSchemas, allOf, oneOf, anyOf, if, then, else
+    """
+    if validator.is_type(schema, "boolean"):
+        return []
+    evaluated_keys = []
+
+    ref = schema.get("$ref")
+    if ref is not None:
+        resolved = validator._resolver.lookup(ref)
+        evaluated_keys.extend(
+            find_evaluated_property_keys_by_schema(
+                validator.evolve(
+                    schema=resolved.contents,
+                    _resolver=resolved.resolver,
+                ),
+                instance,
+                resolved.contents,
+            ),
+        )
+
+    dynamicRef = schema.get("$dynamicRef")
+    if dynamicRef is not None:
+        resolved = validator._resolver.lookup(dynamicRef)
+        evaluated_keys.extend(
+            find_evaluated_property_keys_by_schema(
+                validator.evolve(
+                    schema=resolved.contents,
+                    _resolver=resolved.resolver,
+                ),
+                instance,
+                resolved.contents,
+            ),
+        )
+
+    for keyword in [
+        "properties", "additionalProperties", "unevaluatedProperties",
+    ]:
+        if keyword in schema:
+            schema_value = schema[keyword]
+            if validator.is_type(schema_value, "boolean") and schema_value:
+                evaluated_keys += instance.keys()
+
+            elif validator.is_type(schema_value, "object"):
+                for property in schema_value:
+                    if property in instance:
+                        evaluated_keys.append(property)
+
+    if "patternProperties" in schema:
+        for property in instance:
+            for pattern in schema["patternProperties"]:
+                if re.search(pattern, property):
+                    evaluated_keys.append(property)
+
+    if "dependentSchemas" in schema:
+        for property, subschema in schema["dependentSchemas"].items():
+            if property not in instance:
+                continue
+            evaluated_keys += find_evaluated_property_keys_by_schema(
+                validator, instance, subschema,
+            )
+
+    for keyword in ["allOf", "oneOf", "anyOf"]:
+        if keyword in schema:
+            for subschema in schema[keyword]:
+                errs = next(validator.descend(instance, subschema), None)
+                if errs is None:
+                    evaluated_keys += find_evaluated_property_keys_by_schema(
+                        validator, instance, subschema,
+                    )
+
+    if "if" in schema:
+        if validator.evolve(schema=schema["if"]).is_valid(instance):
+            evaluated_keys += find_evaluated_property_keys_by_schema(
+                validator, instance, schema["if"],
+            )
+            if "then" in schema:
+                evaluated_keys += find_evaluated_property_keys_by_schema(
+                    validator, instance, schema["then"],
+                )
+        elif "else" in schema:
+            evaluated_keys += find_evaluated_property_keys_by_schema(
+                validator, instance, schema["else"],
+            )
+
+    return evaluated_keys