def _isspecial(name):
    return name.startswith("__") and name.endswith("__")

class Namespace(object):
    """Namespace([namespace|dict|seq], **kwargs) -> Namespace object

    The new Namespace object's attributes are initialized from (if
    provided) either another Namespace object's attributes, a
    dictionary, or a sequence of (name, value) pairs, then from the
    name=value pairs in the keyword argument list.
    """

    def __init__(*args, **kwargs):
        """Initializes the attributes of a Namespace instance.
        
        Calling __init__ from a subclass is optional. Any _required_
        initialisation will be done in __new__. Subclasses should
        preserve this characteristic.
        """
        # inheritance-friendly update call
        type(args[0]).update(*args, **kwargs)

    def __getattribute__(self, name):
        """Namespaces only use __dict__ and __getattr__
        for non-magic attribute names.
        Class attributes and descriptors like property() are ignored
        """
        getattribute = super(Namespace, self).__getattribute__
        try:
            return getattribute("__dict__")[name]
        except KeyError:
            if _isspecial(name):
                # Employ the default lookup system for magic names
                return getattribute(name)
            else:
                # Skip the default lookup system for normal names
                if hasattr(self, "__getattr__"):
                    return getattribute("__getattr__")(name)
                else:
                    raise AttributeError('%s instance has no attribute %s'
                                         % (type(self).__name__, name))

    def __setattr__(self, name, val):
        """Namespaces only use __dict__ for non-magic attribute names.
        Descriptors like property() are ignored"""
        if _isspecial(name):
            super(Namespace, self).__setattr__(name, val)
        else:
            self.__dict__[name] = val

    def __delattr__(self, name):
        """Namespaces only use __dict__ for non-magic attribute names.
        Descriptors like property() are ignored"""
        if _isspecial(name):
            super(Namespace, self).__delattr__(name)
        else:
            del self.__dict__[name]

    def __eq__(self, other):
        """x.__eq__(y) <==> x == y

        Two Namespace objects are considered equal if they have the
        same attributes and the same values for each of those
        attributes.
        """
        return (other.__class__ == self.__class__ and
                self.__dict__ == other.__dict__)

    def __repr__(self):
        """x.__repr__() <==> repr(x)

        If all attribute values in this namespace (and any nested
        namespaces) are reproducable with eval(repr(x)), then the
        Namespace object is also reproducable for eval(repr(x)).
        """
        return '%s(%s)' % (
            type(self).__name__,
            ', '.join('%s=%r' % (k, v) for k, v in
                      sorted(self.__dict__.iteritems())))

    def update(*args, **kwargs):
        """Namespace.update(ns, [ns|dict|seq,] **kwargs) -> None

        Updates the first Namespace object's attributes from (if
        provided) either another Namespace object's attributes, a
        dictionary, or a sequence of (name, value) pairs, then from
        the name=value pairs in the keyword argument list.
        """
        if not 1 <= len(args) <= 2:
            raise TypeError('expected 1 or 2 arguments, got %i' %
                            len(args))
        self = args[0]
        if not isinstance(self, Namespace):
            raise TypeError('first argument to update should be '
                            'Namespace,  not %s' %
                            type(self).__name__)
        if len(args) == 2:
            other = args[1]
            if isinstance(other, Namespace):
                other = other.__dict__
            try:
                self.__dict__.update(other)
            except (TypeError, ValueError):
                raise TypeError('cannot update Namespace with %s' %
                                type(other).__name__)
        self.__dict__.update(kwargs)


class NamespaceView(Namespace):
    """NamespaceView([ns|dict]) -> new Namespace view of the dict

    Creates a Namespace that is a view of the original dictionary,
    that is, changes to the Namespace object will be reflected in
    the dictionary, and vice versa.
    For namespaces, the view is of the other namespace's attributes.
    """
    def __init__(self, orig):
        if isinstance(orig, Namespace):
            self.__dict__ = orig.__dict__
        else:
            self.__dict__ = orig

class LockedView(NamespaceView):
    """LockedView(dict) -> new Namespace view of the dict

    Creates a NamespaceView that prevents addition of deletion
    of names in the namespace. Existing names can be rebound.
    """
    def __setattr__(self, name, val):
        getattr(self, name)
        self.__dict__[name] = val

    def __delattr__(self, name):
        raise TypeError("%s does not permit deletion of attributes"
                        % type(self).__name__)

class NamespaceChain(NamespaceView):
    """NamespaceChain(dict, *chain) -> new attribute lookup chain

    The new NamespaceChain is firstly a standard NamespaceView for
    the supplied dictionary.
    
    However, when an attribute is looked up and is not found in the
    main dictionary, the sequence of chained objects is searched
    sequentially for an object with such an attribute.  The first
    such attribute found is returned, or an AttributeError is raised
    if none is found.

    The list of chained objects is stored in the __namespaces__
    attribute.
    """
    def __init__(self, head, *args):
        NamespaceView.__init__(self, head)
        self.__namespaces__ = args

    def __getattr__(self, name):
        """Return the first such attribute found in the object list

        This is only invoked for attributes not found in the head
        namespace.
        """
        for obj in self.__namespaces__:
            try:
                return getattr(obj, name)
            except AttributeError:
                pass
        raise AttributeError('%s instance has no attribute %s'
                             % (type(self).__name__, name))

class Record(LockedView):
    _subfield_prefix = "_sub_"
    def __init__(self):
        """Record() -> Record instance

        Instantiates a Namespace populated based on a Record
        subclass definition.
        Normal attributes are placed in the instance dictionary
        on initialisation.
        Attributes whose names start with '_sub_' are called, and
        the result placed in the instance dictionary using a name
        without the subfield prefix.
        The subfield prefix used can be changed by setting the
        _subfield_prefix attribute in the subclass
        Setting the subfield prefix to None means no subfields will be
        automatically instantiated, and setting it to "" means that
        every field will be automatically instantiated.
        Any fields starting with an underscore are ignored (this includes
        subfields which start with an underscore after the subfield prefix
        has been stripped).

        For example:
        Py> from namespaces import Record
        Py> class Example(Record):
        ...   a = 1
        ...   b = ""
        ...   class _sub_sf(Record):
        ...     c = 3
        ...   def _sub_calc(): return "Calculated value!"
        ...
        Py> x = Example()
        Py> x
        Example(a=1, b='', calc='Calculated value!', sf=_sub_sf(c=3))
        Py> class Example2(namespaces.Record):
        ...   _subfield_prefix = ""
        ...   a = str
        ...   b = int
        ...   class x(namespaces.Record): pass
        ...   def f(): return "Hi!"
        ...
        Py> x = Example2()
        Py> x
        Example2(a='', b=0, f='Hi!', x=x())
        Py> x.c = 1
        Traceback (most recent call last):
          ...
        AttributeError: Example2 instance has no attribute c
        """
        definition = type(self)
        prefix = definition._subfield_prefix
        prefix_len = len(prefix)
        for field, value in definition.__dict__.iteritems():
            if field.startswith(prefix):
                subfield = field[prefix_len:]
                if not subfield.startswith("_"):
                    # Set the calculated value
                    self.__dict__[subfield] = value()
            elif not field.startswith("_"):
                # Set the value
                self.__dict__[field] = value
 