Blame tools/extra/packager/jsonschema-2.3.0/jsonschema/_utils.py

Packit 534379
import itertools
Packit 534379
import json
Packit 534379
import re
Packit 534379
import os
Packit 534379
Packit 534379
from jsonschema.compat import str_types, MutableMapping, urlsplit
Packit 534379
Packit 534379
Packit 534379
class URIDict(MutableMapping):
Packit 534379
    """
Packit 534379
    Dictionary which uses normalized URIs as keys.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    def normalize(self, uri):
Packit 534379
        return urlsplit(uri).geturl()
Packit 534379
Packit 534379
    def __init__(self, *args, **kwargs):
Packit 534379
        self.store = dict()
Packit 534379
        self.store.update(*args, **kwargs)
Packit 534379
Packit 534379
    def __getitem__(self, uri):
Packit 534379
        return self.store[self.normalize(uri)]
Packit 534379
Packit 534379
    def __setitem__(self, uri, value):
Packit 534379
        self.store[self.normalize(uri)] = value
Packit 534379
Packit 534379
    def __delitem__(self, uri):
Packit 534379
        del self.store[self.normalize(uri)]
Packit 534379
Packit 534379
    def __iter__(self):
Packit 534379
        return iter(self.store)
Packit 534379
Packit 534379
    def __len__(self):
Packit 534379
        return len(self.store)
Packit 534379
Packit 534379
    def __repr__(self):
Packit 534379
        return repr(self.store)
Packit 534379
Packit 534379
Packit 534379
class Unset(object):
Packit 534379
    """
Packit 534379
    An as-of-yet unset attribute or unprovided default parameter.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    def __repr__(self):
Packit 534379
        return "<unset>"
Packit 534379
Packit 534379
Packit 534379
def load_schema(name):
Packit 534379
    """
Packit 534379
    Load a schema from ./schemas/``name``.json and return it.
Packit 534379
Packit 534379
    """
Packit 534379
    schemadir = os.path.join(
Packit 534379
        os.path.dirname(os.path.abspath(__file__)),
Packit 534379
        'schemas'
Packit 534379
    )
Packit 534379
    schemapath = os.path.join(schemadir, '%s.json' % (name,))
Packit 534379
    with open(schemapath) as f:
Packit 534379
        return json.load(f)
Packit 534379
Packit 534379
Packit 534379
def indent(string, times=1):
Packit 534379
    """
Packit 534379
    A dumb version of :func:`textwrap.indent` from Python 3.3.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    return "\n".join(" " * (4 * times) + line for line in string.splitlines())
Packit 534379
Packit 534379
Packit 534379
def format_as_index(indices):
Packit 534379
    """
Packit 534379
    Construct a single string containing indexing operations for the indices.
Packit 534379
Packit 534379
    For example, [1, 2, "foo"] -> [1][2]["foo"]
Packit 534379
Packit 534379
    :type indices: sequence
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    if not indices:
Packit 534379
        return ""
Packit 534379
    return "[%s]" % "][".join(repr(index) for index in indices)
Packit 534379
Packit 534379
Packit 534379
def find_additional_properties(instance, schema):
Packit 534379
    """
Packit 534379
    Return the set of additional properties for the given ``instance``.
Packit 534379
Packit 534379
    Weeds out properties that should have been validated by ``properties`` and
Packit 534379
    / or ``patternProperties``.
Packit 534379
Packit 534379
    Assumes ``instance`` is dict-like already.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    properties = schema.get("properties", {})
Packit 534379
    patterns = "|".join(schema.get("patternProperties", {}))
Packit 534379
    for property in instance:
Packit 534379
        if property not in properties:
Packit 534379
            if patterns and re.search(patterns, property):
Packit 534379
                continue
Packit 534379
            yield property
Packit 534379
Packit 534379
Packit 534379
def extras_msg(extras):
Packit 534379
    """
Packit 534379
    Create an error message for extra items or properties.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    if len(extras) == 1:
Packit 534379
        verb = "was"
Packit 534379
    else:
Packit 534379
        verb = "were"
Packit 534379
    return ", ".join(repr(extra) for extra in extras), verb
Packit 534379
Packit 534379
Packit 534379
def types_msg(instance, types):
Packit 534379
    """
Packit 534379
    Create an error message for a failure to match the given types.
Packit 534379
Packit 534379
    If the ``instance`` is an object and contains a ``name`` property, it will
Packit 534379
    be considered to be a description of that object and used as its type.
Packit 534379
Packit 534379
    Otherwise the message is simply the reprs of the given ``types``.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    reprs = []
Packit 534379
    for type in types:
Packit 534379
        try:
Packit 534379
            reprs.append(repr(type["name"]))
Packit 534379
        except Exception:
Packit 534379
            reprs.append(repr(type))
Packit 534379
    return "%r is not of type %s" % (instance, ", ".join(reprs))
Packit 534379
Packit 534379
Packit 534379
def flatten(suitable_for_isinstance):
Packit 534379
    """
Packit 534379
    isinstance() can accept a bunch of really annoying different types:
Packit 534379
        * a single type
Packit 534379
        * a tuple of types
Packit 534379
        * an arbitrary nested tree of tuples
Packit 534379
Packit 534379
    Return a flattened tuple of the given argument.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    types = set()
Packit 534379
Packit 534379
    if not isinstance(suitable_for_isinstance, tuple):
Packit 534379
        suitable_for_isinstance = (suitable_for_isinstance,)
Packit 534379
    for thing in suitable_for_isinstance:
Packit 534379
        if isinstance(thing, tuple):
Packit 534379
            types.update(flatten(thing))
Packit 534379
        else:
Packit 534379
            types.add(thing)
Packit 534379
    return tuple(types)
Packit 534379
Packit 534379
Packit 534379
def ensure_list(thing):
Packit 534379
    """
Packit 534379
    Wrap ``thing`` in a list if it's a single str.
Packit 534379
Packit 534379
    Otherwise, return it unchanged.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    if isinstance(thing, str_types):
Packit 534379
        return [thing]
Packit 534379
    return thing
Packit 534379
Packit 534379
Packit 534379
def unbool(element, true=object(), false=object()):
Packit 534379
    """
Packit 534379
    A hack to make True and 1 and False and 0 unique for ``uniq``.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    if element is True:
Packit 534379
        return true
Packit 534379
    elif element is False:
Packit 534379
        return false
Packit 534379
    return element
Packit 534379
Packit 534379
Packit 534379
def uniq(container):
Packit 534379
    """
Packit 534379
    Check if all of a container's elements are unique.
Packit 534379
Packit 534379
    Successively tries first to rely that the elements are hashable, then
Packit 534379
    falls back on them being sortable, and finally falls back on brute
Packit 534379
    force.
Packit 534379
Packit 534379
    """
Packit 534379
Packit 534379
    try:
Packit 534379
        return len(set(unbool(i) for i in container)) == len(container)
Packit 534379
    except TypeError:
Packit 534379
        try:
Packit 534379
            sort = sorted(unbool(i) for i in container)
Packit 534379
            sliced = itertools.islice(sort, 1, None)
Packit 534379
            for i, j in zip(sort, sliced):
Packit 534379
                if i == j:
Packit 534379
                    return False
Packit 534379
        except (NotImplementedError, TypeError):
Packit 534379
            seen = []
Packit 534379
            for e in container:
Packit 534379
                e = unbool(e)
Packit 534379
                if e in seen:
Packit 534379
                    return False
Packit 534379
                seen.append(e)
Packit 534379
    return True