Viewing file: _utils.py (5.05 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
import itertools import json import pkgutil import re
from jsonschema.compat import MutableMapping, str_types, urlsplit
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): return len(self.store)
def __repr__(self): return repr(self.store)
class Unset(object): """ An as-of-yet unset attribute or unprovided default parameter. """
def __repr__(self): return "<unset>"
def load_schema(name): """ Load a schema from ./schemas/``name``.json and return it. """
data = pkgutil.get_data("jsonschema", "schemas/{0}.json".format(name)) return json.loads(data.decode("utf-8"))
def indent(string, times=1): """ A dumb version of `textwrap.indent` from Python 3.3. """
return "\n".join(" " * (4 * times) + line for line in string.splitlines())
def format_as_index(indices): """ Construct a single string containing indexing operations for the indices.
For example, [1, 2, "foo"] -> [1][2]["foo"]
Arguments:
indices (sequence):
The indices to format. """
if not indices: return "" return "[%s]" % "][".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. """
if len(extras) == 1: verb = "was" else: verb = "were" return ", ".join(repr(extra) for extra in extras), verb
def types_msg(instance, types): """ Create an error message for a failure to match the given types.
If the ``instance`` is an object and contains a ``name`` property, it will be considered to be a description of that object and used as its type.
Otherwise the message is simply the reprs of the given ``types``. """
reprs = [] for type in types: try: reprs.append(repr(type["name"])) except Exception: reprs.append(repr(type)) return "%r is not of type %s" % (instance, ", ".join(reprs))
def flatten(suitable_for_isinstance): """ isinstance() can accept a bunch of really annoying different types: * a single type * a tuple of types * an arbitrary nested tree of tuples
Return a flattened tuple of the given argument. """
types = set()
if not isinstance(suitable_for_isinstance, tuple): suitable_for_isinstance = (suitable_for_isinstance,) for thing in suitable_for_isinstance: if isinstance(thing, tuple): types.update(flatten(thing)) else: types.add(thing) return tuple(types)
def ensure_list(thing): """ Wrap ``thing`` in a list if it's a single str.
Otherwise, return it unchanged. """
if isinstance(thing, str_types): return [thing] return thing
def equal(one, two): """ Check if two things are equal, but evade booleans and ints being equal. """ 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.
Successively tries first to rely that the elements are hashable, then falls back on them being sortable, and finally falls back on brute force. """
try: return len(set(unbool(i) for i in container)) == len(container) except TypeError: try: sort = sorted(unbool(i) for i in container) sliced = itertools.islice(sort, 1, None) for i, j in zip(sort, sliced): if i == j: return False except (NotImplementedError, TypeError): seen = [] for e in container: e = unbool(e) if e in seen: return False seen.append(e) return True
|