Commits

pfw committed 0b4d4cb

Use qp.spec and qp.keep

Comments (0)

Files changed (3)

flask_durus/durus.py

 
 from UserDict import IterableUserDict
 
-from .spec import either, spec, nspec, init, length, add_getters_and_setters
-from .spec import require, get_spec_problems, specify, identifier_pattern, both
-from .spec import datetime_with_tz, sequence, instance, mapping, match, get_specs
-from .keep import Keyed, Stamped, Keep, Counter
+from qp.spec import either, spec, nspec, init, length, add_getters_and_setters
+from qp.spec import require, get_spec_problems, specify, identifier_pattern, both
+from qp.spec import datetime_with_tz, sequence, instance, mapping, match, get_specs
+from qp.keep import Keyed, Stamped, Keep, Counter
 
 from flask import _request_ctx_stack, redirect, url_for
 
         """
         return self._indexes.get(name, None)
 
-
-    # def on_commit(self):
-    #     """
-    #     When commiting this keep, run through all changed items in it and update the indexes.
-    #     """
-    #     for item in self.mapping.itervalues():
-    #         if item._p_is_unsaved():
-    #             item.update_indexes(value)
-
-    # def create_indexes(self):
-    #     """()
-    #     Create all indexes bases on callables on the value_spec class that start with 'key_for'
-    #     """
-    #     for attr in self.value_spec.__dict__.keys():
-    #         if attr.startswith('key_for_') and callable(getattr(self.value_spec, attr)):
-    #             # index key
-    #             print attr
-    #             self._indexes.setdefault(attr.split('key_for_')[1], BTree())
-
-    # def update_indexes(self, value=None):
-    #     """(value:Persistent|None)
-    #     Update the indexes for this keep, if value is specified, only update indexes for it.
-    #     """
-    #     items = [value] if value else self.mapping.itervalues()
-    #     for name, index in self._indexes.items():
-    #         for item in items:
-    #             if not item._p_oid or item._p_is_unsaved():
-    #                 print "update index:", name, item
-                    
-    #                 # remove existing entries in index
-    #                 existing_key = item._indexes.get(name, None)
-    #                 if existing_key:
-    #                     del(index[existing_key])
-    #                     del(item._indexes[name])
-
-    #                 # add new entries to index
-    #                 key = getattr(item, "key_for_%s" % name)()
-    #                 index[(key, item.key)] = item
-    #                 item._indexes[name] = (key, item.key)
-
-
-
-
-

flask_durus/keep.py

-"""
-$URL: svn+ssh://sting.mems-exchange.org/repos/trunk/DurusWorks/qp/lib/keep.py $
-$Id: keep.py 32474 2010-06-09 15:09:26Z dbinger $
-"""
-from __future__ import absolute_import
-
-from durus.btree import BTree
-from durus.persistent import PersistentObject
-from durus.persistent_dict import PersistentDict
-
-from .spec import either, datetime_without_tz, mapping, spec, integer
-from .spec import require, get_spec_problems, anything, specify
-
-from datetime import datetime
-
-def rand_int(bits):
-    bytes, remainder = divmod(bits, 8)
-    if remainder == 0:
-        return int(randbytes(bytes), 16)
-    else:
-        return int(randbytes(bytes + 1), 16) >> (8 - remainder)
-
-class Keyed (object):
-    """
-    An item with an int key used as a key in an Keep.
-    Note that the key attribute is set when the item is put in the Keep,
-    so there is no set_key() method.
-    This is a mixin for PersistentObject classes.
-    """
-    key_is = integer
-
-    __slots__ = []
-
-    def __init__(self):
-        assert isinstance(self, PersistentObject)
-        self.key = None
-
-    def get_key(self):
-        return self.key
-
-
-class KeyCounter (PersistentObject):
-    """
-    The base class.  Generates keys using random 64 bit ints.
-    """
-    def next(self):
-        """() -> integer
-        This base implementation just uses a big random number.
-        """
-        return rand_int(64)
-
-
-class Counter (KeyCounter):
-    """
-    Generates keys by incrementing them.
-    """
-    next_available_is = integer
-
-    __slots__ = ['next_available']
-
-    def __init__(self):
-        self.next_available = 1
-
-    def next(self):
-        result = self.next_available
-        self.next_available = self.next_available + 1
-        return result
-
-
-class GrowingRandomCounter (KeyCounter):
-    """
-    Keep a key counter that generates keys randomly, and gradually
-    expands the numbers of bits in the random numbers.
-    The idea is to take advantage of randomly distributed keys, but
-    to try to keep the numbers relatively small.
-    """
-    bits_is = integer
-    used_is = integer
-
-    __slots__ = ['bits', 'used']
-
-    def __init__(self):
-        specify(self, bits=10, used=0)
-
-    def next(self):
-        self.used = self.used + 1
-        # If more than 1% of the possible values have been used,
-        # double the space of possible values.
-        if (self.used / (2 ** self.bits)) > 0.01:
-            self.bits += 1
-        return rand_int(self.bits)
-
-
-class Keep (object):
-    """
-    A simple database that stores a mapping of objects by key.
-    This is a mixin for PersistentObject classes.
-    """
-    value_spec_is = spec(
-        anything,
-        "Specifies the type of values allowed in mapping")
-    mapping_is = mapping({integer:Keyed}, either(PersistentDict, BTree))
-    key_counter_is = KeyCounter
-    __slots__ = []
-
-    def __init__(self, value_spec=Keyed, mapping_class=BTree, counter_class=Counter):
-        assert isinstance(self, PersistentObject)
-        self.mapping = mapping_class()
-        self.value_spec = value_spec
-        self.set_counter(counter_class())
-
-    def set_counter(self, counter):
-        specify(self, key_counter=counter)
-
-    def __len__(self):
-        return len(self.mapping)
-
-    def get_mapping(self):
-        return self.mapping
-
-    def get(self, key, default=None):
-        return self.mapping.get(key, default)
-
-    def itervalues(self):
-        for value in self.mapping.itervalues():
-            yield value
-
-    def iterkeys(self):
-        for key in self.mapping.iterkeys():
-            yield key
-
-    def iteritems(self):
-        for item in self.mapping.iteritems():
-            yield item
-
-    def add(self, value):
-        require(value, self.value_spec)
-        assert value.key is None
-        for attempt in range(1000):
-            value.key = self.key_counter.next()
-            if value.key not in self.mapping:
-                break
-        else:
-            raise KeyError('Unable to find unused key for %r.' % value)
-        if get_spec_problems(value):
-            raise TypeError(''.join(get_spec_problems(value)))
-        self.mapping[value.key] = value
-
-    def remove(self, value):
-        require(value, self.value_spec)
-        assert value.key is self.mapping[value.key].key
-        del self.mapping[value.key]
-
-
-class Stamped (object):
-    """
-    Provides a timestamp.
-    This is a mixin for PersistentObject classes.  
-    """
-    stamp_is = datetime_without_tz
-
-    __slots__ = []
-
-    def __init__(self):
-        assert isinstance(self, PersistentObject)
-        self.set_stamp()
-
-    def get_stamp(self):
-        return self.stamp
-
-    def set_stamp(self):
-        self.stamp = datetime.utcnow()
-
-
-def stamp_sorted(stamped_sequence):
-    items = [(x.stamp, x) for x in stamped_sequence]
-    return [x for (stamp, x) in sorted(items)]
-
-def reverse_stamp_sorted(stamped_sequence):
-    result = stamp_sorted(stamped_sequence)
-    result.reverse()
-    return result
-

flask_durus/spec.py

-"""
-$URL: svn+ssh://sting.mems-exchange.org/repos/trunk/DurusWorks/qp/lib/spec.py $
-$Id: spec.py 33984 2011-06-22 18:51:03Z rmasse $
-
-This module provides tools for matching values to specs.
-
-In particular, it provides the functions
-  match(),
-  require()
-
-This module also provides tools for constructing specs,
-using them to specify and validate instance attributes.
-"""
-
-import re
-from datetime import datetime
-from types import FunctionType, MethodType
-import sys
-
-epoch = datetime(1970,1,1)
-
-if sys.version < "3":
-    from __builtin__ import unicode, long
-    unicode_string = unicode
-    byte_string = str
-    number_classes = (int, long, float)
-else:
-    from builtins import bytes
-    unicode_string = str
-    byte_string = bytes
-    number_classes = (int, float)
-
-string_classes = (unicode_string, byte_string)
-
-def format_spec(spec):
-    """
-    Returns the canonical string representation of the spec.
-    """
-    if spec is None:
-        return 'None'
-    if type(spec) is tuple:
-        return '(%s)' % ', '.join(map(format_spec, spec))
-    if type(spec) is list:
-        return '[%s]' % ', '.join(map(format_spec, spec))
-    if type(spec) is dict:
-        return ('{%s}' %
-                ', '.join(["%s: %s" % (format_spec(key_type),
-                                       format_spec(val_type)) #nocover
-                           for key_type, val_type in spec.items()]))
-    if hasattr(spec, '__name__'):
-        return spec.__name__
-    if isinstance(spec, string_classes):
-        return repr(spec)
-    return str(spec)
-
-class SpecOperator (object):
-    """
-    The superclass of all of the spec operators.
-    Constructors of subclasses should assign to self.args
-    a tuple of the arguments to the constructor.
-    """
-
-    def get_args(self):
-        return self.args
-
-    def format_args(self):
-        return ', '.join(map(format_spec, self.get_args()))
-
-    def __str__(self):
-        return "%s(%s)" % (self.__class__.__name__, self.format_args())
-
-    def explain_difference(self, value):
-        return format_expected_got(self, value)
-
-def match(value, spec):
-    """
-    Return True or False depending on whether or not value matches
-    the given type specification.  Here are the available type
-    specifications:
-
-    Type Spec                Matches
-
-    a type or class         any instance of the type
-
-    a callable              anything for which <spec>(value) is true,
-                            so you can do arbitrary checking.
-
-    a list (or tuple)       any list (or tuple) whose elements all match the
-    with length 1           enclosed type specification.
-
-    a list (or tuple)       any list (tuple) whose sequence of elements match
-    with length > 1,        the sequence of corresponding type specifications,
-    not containing None,
-    or any string or numeric
-    or bool literal.
-
-    a tuple with            any value that matches any of the items in the tuple.
-    length > 1
-    containing None,
-    or any string or
-    numeric
-    literal.
-
-    a set                   any set whose elements match any of the elements in
-                            the type specification.
-
-    a dict                  any dict for which every item matches some item in
-                            this dictionary.
-
-    other                   any value for which value == other.
-
-    """
-    if isinstance(spec, (FunctionType, SpecOperator, Specification)):
-        return spec(value)
-    spec_type = type(spec)
-    if spec_type is tuple and len(spec) > 1:
-        # Possible disjunction.
-        for element in spec:
-            if (element is None or
-                type(element) in (float, int, bool) or
-                isinstance(element, string_classes)):
-                # Definite disjunction.
-                for element in spec:
-                    if match(value, element):
-                        return True
-                return False
-    if spec_type in (list, tuple):
-        if type(value) is not spec_type:
-            return False
-        if len(spec) == 1:
-            element_type = spec[0]
-            for element in value:
-                if not match(element, element_type):
-                    return False
-            return True
-        else:
-            if len(value) != len(spec):
-                return False
-            for element, element_type in zip(value, spec):
-                if not match(element, element_type):
-                    return False
-            return True
-    if spec_type is dict:
-        if type(value) is not dict:
-            return False
-        for key, val in value.items():
-            for key_type, value_type in spec.items():
-                if (match(key, key_type) and
-                    match(val, value_type)):
-                    break
-            else:
-                return False
-        return True
-    if spec_type is set:
-        for element in value:
-            for element_type in spec:
-                if match(element, element_type):
-                    break
-            else:
-                return False
-        return True
-    try:
-        return isinstance(value, spec)
-    except TypeError:
-        pass
-    if spec_type is type(value):
-        return value == spec
-    if hasattr(spec, '__call__'):
-        return spec(value)
-    try:
-        return value == spec
-    except (TypeError, ValueError, AssertionError):
-        pass
-    return False
-
-def format_expected_got(spec, value):
-    return ('\n  Expected: %s\n'
-            '  Got: %r\n') % (format_spec(spec), value)
-
-def require(value, spec, message=None):
-    if not match(value, spec):
-        if isinstance(spec, SpecOperator):
-            error = spec.explain_difference(value)
-        else:
-            error = format_expected_got(spec, value)
-        if message:
-            error = '(%s)%s' % (message, error)
-        raise TypeError(error)
-
-class Anything (object):
-    """
-    The universal spec.
-    """
-    def __str__(self):
-        return "anything"
-
-    def __call__(self, value):
-        return True
-
-anything = Anything()
-
-class sequence (SpecOperator):
-
-    """
-    Use this to specify a sequence.
-    """
-
-    def __init__(self, element_spec=anything, container_spec=anything):
-        self.container_spec = container_spec
-        self.element_spec = element_spec
-        self.args = (element_spec, container_spec)
-
-    def __call__(self, value):
-        if not match(value, self.container_spec):
-            return False
-        element_spec = self.element_spec
-        for element in value:
-            if not match(element, element_spec):
-                return False
-        return True
-
-
-class mapping (SpecOperator):
-
-    """
-    Use this to specify a mapping.
-    """
-
-    def __init__(self, dict_spec=anything, container_spec=anything):
-        self.dict_spec = dict_spec
-        self.container_spec = container_spec
-        self.args =  (self.dict_spec, container_spec)
-
-    def __call__(self, value):
-        if not match(value, self.container_spec):
-            return False
-        try:
-            dict_value = dict(value.items())
-        except AttributeError:
-            return False
-        if not match(dict_value, self.dict_spec):
-            return False
-        return True
-
-class subclass (SpecOperator):
-
-    """
-    Use this to specify a subclass of a given class.
-    """
-
-    def __init__(self, klass):
-        self.klass = klass
-        self.args = (klass,)
-
-    def __call__(self, value):
-        try:
-            return issubclass(value, self.klass)
-        except TypeError:
-            return False
-
-
-class instance (SpecOperator):
-
-    """
-    Use this to specify an instance of a class with a given name
-    when the class itself is not available.
-    """
-
-    def __init__(self, klass_name):
-        self.klass_name = klass_name
-        self.args = (klass_name,)
-
-    def __call__(self, value):
-        if hasattr(value, '__class__'):
-            classes = [value.__class__]
-            while classes:
-                if classes[0].__name__ == self.klass_name:
-                    return True
-                classes = classes[1:] + list(classes[0].__bases__)
-        return False
-
-
-class ConnectiveSpecOperator (SpecOperator):
-
-    def __init__(self, *specs):
-        self.specs = specs
-        self.args = self.specs
-
-
-class no (ConnectiveSpecOperator):
-
-    """
-    Use this to specify a negation of specs.
-    Example: no(None)
-    """
-
-    def __call__(self, value):
-        for spec in self.specs:
-            if match(value, spec):
-                return False
-        return True
-
-
-class both (ConnectiveSpecOperator):
-
-    """
-    Use this to specify a conjunction of specs.
-    Example:
-      both([int], length(3)) specifies values that are lists of 3 ints.
-    """
-
-    def __call__(self, value):
-        for spec in self.specs:
-            if not match(value, spec):
-                return False
-        return True
-
-    def explain_difference(self, value):
-        error = format_expected_got(self, value)
-        for spec in self.specs:
-            if not match(value, spec):
-                error += "  (which does not match %s)" % format_spec(spec)
-                break
-        return error
-
-class either (ConnectiveSpecOperator):
-
-    """
-    Use this to specify a disjunction of specs.
-    Examples:
-      either(int, str) specifies values that are ints or strs.
-    """
-
-    def __call__(self, value):
-        for spec in self.specs:
-            if match(value, spec):
-                return True
-        return False
-
-
-class proper (both):
-
-    """
-    Use this to specify an instance with attributes that agree with the
-    attribute specifications for this class.
-    If arguments are provided, they are additional specs which the instance
-    must satisfy.
-    """
-
-    def __call__(self, value):
-        return both.__call__(self, value) and get_spec_problems(value) == []
-
-
-class interval (SpecOperator):
-
-    def __init__(self, min=anything, max=anything):
-        self.min = min
-        self.max = max
-
-    def format_args(self):
-        if self.max is anything:
-            if self.min is anything:
-                return ''
-            return format_spec(self.min)
-        else:
-            return '%s, %s' % (format_spec(self.min), format_spec(self.max))
-
-    def __call__(self, value):
-        if self.min not  in (None, anything):
-            if self.max is anything:
-                return value >= self.min
-            elif value < self.min:
-                return False
-        if self.max not  in (None, anything):
-            if self.min is anything:
-                return value <= self.max
-            elif value > self.max:
-                return False
-        return True
-
-
-class length (interval):
-
-    """
-    Use this to specify specs by ranges of length.
-    Examples:
-      length(3, None) specifies values of length 3 or more.
-      length(3) specifies values of length 3.
-    """
-
-    def __call__(self, value):
-        return interval.__call__(self, len(value))
-
-
-class eq (SpecOperator):
-
-    """
-    Use this to specify specs exact value.
-    Examples:
-      eq(SpecOperator) matches the SpecOperator class, but nothing else.
-
-    """
-
-    def __init__(self, value):
-        self.value = value
-
-    def format_args(self):
-        return repr(self.value)
-
-    def __call__(self, value):
-        return value is self.value
-
-
-class equal (SpecOperator):
-
-    """
-    Use this to specify specs exact value.
-    Examples:
-      eq([2,3]) matches any list [2,3]
-
-    """
-
-    def __init__(self, value):
-        self.value = value
-
-    def format_args(self):
-        return repr(self.value)
-
-    def __call__(self, value):
-        return value == self.value
-
-boolean = either(True, False, 0, 1)
-
-if sys.version < "3":
-    integer = either(int, long)
-else:
-    integer = int
-
-class charset (SpecOperator):
-
-    def __init__(self, charset):
-        self.charset = charset
-
-    def __str__(self):
-        return self.charset
-
-    def __call__(self, value):
-        if isinstance(value, unicode_string):
-            try:
-                value.encode(self.charset)
-            except UnicodeEncodeError:
-                return False
-        elif isinstance(value, byte_string):
-            try:
-                unicode_string(value, self.charset)
-            except UnicodeDecodeError:
-                return False
-        else:
-            return False
-        return True
-
-
-ascii = charset('ascii')
-
-
-class String (SpecOperator):
-
-    """
-    This is the common string class, including ascii byte sequences and
-    all unicode instances.
-    """
-
-    def __str__(self):
-        return 'string'
-
-    def __call__(self, value):
-        if isinstance(value, unicode_string):
-            return True
-        elif isinstance(value, byte_string):
-            try:
-                unicode_string(value, 'ascii')
-                return True
-            except UnicodeDecodeError:
-                return False
-        return False
-
-string = String()
-
-
-class pattern (SpecOperator):
-    """
-    Matches strings that match the regular expression.
-    """
-    def __init__(self, pattern):
-        self.pattern = re.compile(pattern)
-        self.args = (pattern,)
-
-    def __call__(self, value):
-        try:
-            return bool(self.pattern.match(value))
-        except TypeError:
-            return False
-
-identifier_pattern = pattern('[a-zA-Z_][a-zA-Z0-9_]*$')
-
-class with_attribute (SpecOperator):
-    """
-    Matches values with attributes matching given specs.
-    A keyword argument gives the spec for each attribute.
-    """
-    def __init__(self, **attribute_specs):
-        self.attribute_specs = attribute_specs
-
-    def __call__(self, value):
-        for attribute, spec in self.attribute_specs.items():
-            if (not hasattr(value, attribute) or
-                not match(getattr(value, attribute), spec)):
-                return False
-        return True
-
-    def format_args(self):
-        return ', '.join(['%s=%s' % (name, format_spec(spec))
-                          for name, spec in sorted(self.attribute_specs.items())])
-
-
-datetime_without_tz = both(datetime, with_attribute(tzinfo=None))
-datetime_with_tz = both(datetime, with_attribute(tzinfo=no(None)))
-
-class Callable (object):
-
-    def __str__(self):
-        return 'callable'
-
-    def __call__(self, value):
-        return hasattr(value, '__call__')
-
-callable = Callable()
-
-class Specification:
-    """
-    Instance attributes:
-      doc : string
-      spec : anything
-    """
-
-    def __init__(self, spec, doc=''):
-        self.doc = doc
-        self.spec = spec
-
-    def __call__(self, *value):
-        """
-        if there are no arguments call the spec to instantiate a conforming value
-        otherwise verify that the argument conforms.
-        """
-        if len(value) == 0:
-            return self.spec()
-        assert len(value) == 1, len(value)
-        return match(value[0], self.spec)
-
-    def __str__(self):
-        """-> str
-        Return a formatted string describing this spec and corresponding doc.
-        """
-        doc = '\n  '.join([line.strip()
-                           for line in self.doc.split('\n')])
-        if doc:
-            return self.format_spec() + '\n  ' + doc
-        else:
-            return self.format_spec()
-
-    def valid(self, value):
-        """(value : anything) -> bool
-        Does the value match this spec?
-        """
-        return match(value, self.spec)
-
-    def format_spec(self):
-        """() -> str
-        Return a string version of the spec.
-        """
-        return format_spec(self.spec)
-
-class Optional(Specification):
-    """
-    This specifies a value that is not required to be present.
-    """
-    def format_spec(self):
-        """() -> str
-        Return a string version of the spec.
-        """
-        return "%s (optional)" % format_spec(self.spec)
-
-def get_spec(klass, name):
-    """(klass:anything, name:str) -> anything
-    """
-    value = getattr(klass, name)
-    # functions as specifiers must be unwrapped, since
-    # assignment to class variables changes them.
-    if type(value) is MethodType: # normal classes
-        spec = value.im_func
-    else:
-        spec = value
-    return spec
-
-def spec(spec, *docs):
-    """(anything, *str) -> Specification
-    An alternative Specification constructor.
-    """
-    doc = '\n'.join(docs)
-    return Specification(spec, doc)
-
-def optional(spec, *docs):
-    """(anything, *str) -> Specification
-    An alternative Specification constructor.
-    """
-    doc = '\n'.join(docs)
-    return Optional(spec, doc)
-
-def nspec(spec, *docs):
-    """(anything, *str) -> Specification
-    Like spec, but this uses a modified Specification (if needed) to make
-    sure that None is a valid value.
-    For applications that always want None as a valid value, this
-    allows us to avoid using the either(None,*) pattern around every spec.
-    """
-    doc = '\n'.join(docs)
-    s = Specification(spec, doc)
-    if s.valid(None):
-        return s
-    if isinstance(spec, either):
-        return Specification(either(None, *spec.get_args()), doc)
-    return Specification(either(None, spec), doc)
-
-def get_specs(klass):
-    """(klass:anything) -> { str : anything }
-    Returns a dictionary mapping names to specs that apply to instances of
-    klass.  Specs are distinguished by the following naming convention:
-    A class attribute whose name ends in '_is' specifies an instance
-    attribute without the suffix.
-    Example:
-    class A:
-        color_is = either(str, None)
-        def __init__(self, x):
-            self.color = x
-    """
-    specs = {}
-    for name in dir(klass):
-        if name.endswith('_is'):
-            specs[name[:-3]] = get_spec(klass, name)
-    return specs
-
-def persistent_vars(obj):
-    """() -> dict
-    This is like the built-in vars() function, except that it also works
-    for PersistentObject instances or other instances that use slots for
-    data attributes.
-    """
-    if hasattr(obj, '__getstate__'):
-        return obj.__getstate__() or {}
-    elif hasattr(obj, '__dict__'):
-        return vars(obj)
-    else:
-        result = {}
-        for name in obj.__slots__:
-            if hasattr(obj, name):
-                result[name] = getattr(obj, name)
-        return result
-
-def get_spec_problems(x, specs=None):
-    """(x:anything, specs:{str:Spec}) -> [str]
-    Return a list of reasons why the attributes of this
-    instance do not match the specs.
-    Use provided specs for speed if you already
-    have the specs of the class of x.
-    """
-    reasons = []
-    if specs is None:
-        specs = get_specs(x.__class__)
-    for name, spec in specs.items():
-        if not hasattr(x, name):
-            if not isinstance(spec, Optional):
-                reasons.append(
-                    ('%r.%s: Missing\n'
-                    '  Expected: %s\n') % (x, name, format_spec(spec)))
-        else:
-            value = getattr(x, name)
-            if not match(value, spec):
-                reasons.append(
-                    ('%r.%s:\n' #nocover
-                     '  Expected: %s\n'
-                     '  Got: %r\n') % ( #nocover
-                    x, name, format_spec(spec), value))
-    for name, value in persistent_vars(x).items():
-        if not name in specs:
-            reasons.append('Found non-specified attribute: %r.%s (=%r)' %
-                           (x, name, value))
-    return reasons
-
-def get_spec_doc(klass):
-    """(klass:Specified) -> str
-    Return a string containing the docs of all specs of klass.
-    """
-    spec_items = sorted(get_specs(klass).items())
-    return '\n'.join(["%s: %s" % (name, format_spec(spec))
-                      for name, spec in spec_items])
-
-def get_spec_report(instances):
-    """(instances: [InstanceType]) -> str|None
-    Study the instances with respect to their attribute specs.
-    The instances must all be of the same class.
-    If any instance does not satisfy the specs, return a
-    string explaining the problem.
-    If all instances satisfy the specs, return a message reporting
-    the number of instances verified.
-    If the class of the instances has no specifications,
-    return a message that says so.
-    If there are no instances, return None.
-    """
-    count = 0
-    klass = specs = None
-    for instance in instances:
-        if klass is None:
-            klass = instance.__class__
-            specs = get_specs(klass)
-            if not specs:
-                return "\nunspecified " + klass.__name__
-        assert instance.__class__ is klass
-        count += 1
-        instance_problems = get_spec_problems(instance, specs=specs)
-        if instance_problems:
-            return "\n%s:\n" % klass.__name__ + "\n".join(instance_problems)
-    return klass and "\n%s: %s ok\n" % (klass.__name__ , count)
-
-def specify(obj, **attributes_values):
-    """(obj:object, **attributes_values:{str:anything})
-    Set object attributes given as keywords.
-    Raise a TypeError if any value does match a spec,
-    and AttributeError if no corresponding spec is found.
-    """
-    for attribute, value in attributes_values.items():
-        require(value, getattr(obj.__class__, attribute + '_is'))
-        setattr(obj, attribute, value)
-
-def init(obj, **attributes_values):
-    """(obj:object, **attributes_values:{str:anything})
-    Set object attributes given as keywords.
-    Raise a TypeError if any value does match a spec,
-    and AttributeError if no corresponding spec is found.
-    In addition, all other specified attributes are set to None,
-    without any type checking.
-    """
-    for name in get_specs(obj.__class__):
-        if not hasattr(obj, name):
-            setattr(obj, name, None)
-    specify(obj, **attributes_values)
-
-def add_getters(klass):
-    """
-    Add trivial getter method for each specified attribute
-    for which no such method currently exists.
-    """
-    def add_getter(klass, name):
-        accessor_name = 'get_' + name
-        if not hasattr(klass, accessor_name):
-            def get_specified_attribute(self):
-                return getattr(self, name)
-            get_specified_attribute.__name__ = accessor_name
-            setattr(klass, accessor_name, get_specified_attribute)
-    for name in get_specs(klass):
-        add_getter(klass, name)
-
-def add_setters(klass):
-    """
-    Add trivial setter method for each specified attribute
-    for which no such method currently exists.
-    """
-    def add_setter(klass, name):
-        setter_name = 'set_' + name
-        if not hasattr(klass, setter_name):
-            def f(self, value):
-                require(value, getattr(klass, name + '_is'))
-                setattr(self, name, value)
-            f.__name__ = setter_name
-            setattr(klass, setter_name, f)
-    for name in get_specs(klass):
-        add_setter(klass, name)
-
-def add_getters_and_setters(klass):
-    add_getters(klass)
-    add_setters(klass)
-
-
-class SlottedType (type):
-    """
-    Slotted classes have a __slots__ attribute.
-    The default, provided here, is to have __slots__ = [].
-    """
-    def __new__(self, klass_name, bases, namespace):
-        if '__slots__' not in namespace:
-            namespace['__slots__'] = []
-        return type.__new__(self, klass_name, bases, namespace)
-
-
-class SlotsFromSpecs (SlottedType):
-    """
-    Classes with this metaclass get a __slots__ value that is constructed
-    from the attributes (including inherited ones) whose names end with "_is".
-    """
-    def __new__(self, klass_name, bases, namespace):
-        if '__slots__' in namespace:
-            raise TypeError(
-                "Specified class %s already has __slots__: %s" %
-                (klass_name, namespace['__slots__']))
-        else:
-            names = set()
-            for name in namespace:
-                if name.endswith('_is'):
-                    names.add(name[:-3])
-            for base in bases:
-                for name in dir(base):
-                    if name.endswith('_is'):
-                        names.add(name[:-3])
-            namespace['__slots__'] = sorted(names)
-        return type.__new__(self, klass_name, bases, namespace)
-
-Specified = SlotsFromSpecs('Specified', (object,), dict(__doc__=""""
-    This mixin class has a metaclass that uses attribute specs to build
-    a __slots__ list for the class.
-    """))
-
-Mixin = SlottedType('Mixin', (object,), dict(__doc__=""""
-    This mixin class has a metaclass that sets __slots__ = [].
-    This allows subclasses to use slots for attributes.
-    """))