Metadata-Version: 1.1
Name: node
Version: 1.2
Summary: Building data structures as node trees
Home-page: http://github.com/conestack/node
Author: Node Contributors
Author-email: dev@conestack.org
License: Simplified BSD
Description: Node
        ====
        
        .. image:: https://img.shields.io/pypi/v/node.svg
            :target: https://pypi.python.org/pypi/node
            :alt: Latest PyPI version
        
        .. image:: https://img.shields.io/pypi/dm/node.svg
            :target: https://pypi.python.org/pypi/node
            :alt: Number of PyPI downloads
        
        .. image:: https://github.com/conestack/node/actions/workflows/test.yaml/badge.svg
            :target: https://github.com/conestack/node/actions/workflows/test.yaml
            :alt: Test node
        
        
        Overview
        --------
        
        Node is a library to create nested data models and structures.
        
        These data models are described as trees of nodes, optionally with attributes
        and schema definitions.
        
        They utilize:
        
        - Python's
          `mapping and sequence API's <http://docs.python.org/reference/datamodel.html>`_
          for accessing node members.
        - The contract of
          `zope.location.interfaces.ILocation <https://zopelocation.readthedocs.io/en/latest/api.html#zope.location.interfaces.ILocation>`_
          for hierarchy information.
        
        One purpose of this package is to provide a unified API to different backend
        storages. Specific storage related implementations are for example:
        
        - `node.ext.fs <https://pypi.org/project/node.ext.fs>`_
        - `node.ext.ldap <https://pypi.org/project/node.ext.ldap>`_
        - `node.ext.yaml <https://pypi.org/project/node.ext.yaml>`_
        - `node.ext.zodb <https://pypi.org/project/node.ext.zodb>`_
        
        Another usecase is providing interfaces for specific application domains.
        
        E.g. for user and group management,
        `node.ext.ugm <https://pypi.org/project/node.ext.ugm>`_ defines the interfaces.
        Additional it implements a file based default implementation. Then there are
        specific implementations of those interfaces in
        `node.ext.ldap <https://pypi.org/project/node.ext.ldap>`_ and
        `cone.sql <https://pypi.org/project/cone.sql>`_, to access users and groups in
        LDAP and SQL databases.
        
        This package is also used to build in-memory models of all sorts.
        
        E.g.  `yafowil <https://pypi.org/project/yafowil>`_ is a HTML form processing
        and rendering library. It uses node trees for declarative description of the
        form model.
        
        Another one to mention is `cone.app <https://pypi.org/project/cone.app>`_,
        a `Pyramid <https://pypi.org/project/pyramid>`_ based development environment
        for web applications, which uses node trees to describe the application model.
        
        
        Basic Usage
        -----------
        
        There are two basic node types. Mapping nodes and sequence nodes. This
        package provides some basic nodes to start from.
        
        
        Mapping Nodes
        ~~~~~~~~~~~~~
        
        Mapping nodes implement ``node.interfaces.IMappingNode``. A mapping in python
        is a container object that supports arbitrary key lookups and implements the
        methods specified in the ``MutableMapping`` of pythons abstract base classes
        respective ``zope.interface.common.mapping.IFullMapping``.
        
        An unordered node. This can be used as base for trees where order of items
        doesn't matter:
        
        .. code-block:: python
        
            from node.base import BaseNode
        
            root = BaseNode(name='root')
            root['child'] = BaseNode()
        
        An ordered node. The order of items is preserved:
        
        .. code-block:: python
        
            from node.base import OrderedNode
        
            root = OrderedNode(name='orderedroot')
            root['foo'] = OrderedNode()
            root['bar'] = OrderedNode()
        
        With ``printtree`` we can do a quick inspection of our node tree:
        
        .. code-block:: pycon
        
            >>> root.printtree()
            <class 'node.base.OrderedNode'>: orderedroot
              <class 'node.base.OrderedNode'>: foo
              <class 'node.base.OrderedNode'>: bar
        
        
        Sequence Nodes
        ~~~~~~~~~~~~~~
        
        Sequence nodes implement ``node.interfaces.ISequenceNode``. In the context
        of this library, a sequence is an implementation of the methods
        specified in the ``MutableSequence`` of pythons abstract base classes respective
        ``zope.interface.common.collections.IMutableSequence``.
        
        Using a list node:
        
        .. code-block:: python
        
            from node.base import BaseNode
            from node.base import ListNode
        
            root = ListNode(name='listroot')
            root.insert(0, BaseNode())
            root.insert(1, BaseNode())
        
        Check tree structure with ``printtree``:
        
        .. code-block:: pycon
        
            >>> root.printtree()
            <class 'node.base.ListNode'>: listnode
              <class 'node.base.BaseNode'>: 0
              <class 'node.base.BaseNode'>: 1
        
        .. note::
        
            Sequence nodes are introduced as of node 1.0 and are not as feature rich
            as mapping nodes (yet). If you find inconsistencies or missing features,
            please file an issue or create a pull request at github.
        
        
        Behaviors
        ~~~~~~~~~
        
        ``node`` utilizes the `plumber <http://pypi.python.org/pypi/plumber>`_ package.
        
        The different functionalities of nodes are provided as plumbing behaviors:
        
        .. code-block:: python
        
            from node.behaviors import DefaultInit
            from node.behaviors import MappingNode
            from node.behaviors import OdictStorage
            from plumber import plumbing
        
            @plumbing(
                DefaultInit,
                MappingNode,
                OdictStorage)
            class CustomNode:
                pass
        
        When inspecting the ``CustomNode`` class, we can see it was plumbed using given
        behaviors, now representing a complete node implementation:
        
        .. code-block:: pycon
        
            >>> dir(CustomNode)
            ['__bool__', '__class__', '__contains__', '__delattr__', '__delitem__',
            '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
            '__getattribute__', '__getitem__', '__gt__', '__hash__', '__implemented__',
            '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__',
            '__module__', '__name__', '__ne__', '__new__', '__nonzero__', '__parent__',
            '__plumbing__', '__plumbing_stacks__', '__provides__', '__reduce__',
            '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__',
            '__str__', '__subclasshook__', '__weakref__', 'acquire', 'clear', 'copy',
            'deepcopy', 'detach', 'filtereditems', 'filtereditervalues', 'filteredvalues',
            'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys',
            'name', 'noderepr', 'parent', 'path', 'pop', 'popitem', 'printtree', 'root',
            'setdefault', 'storage', 'treerepr', 'update', 'values']
        
        Please read the documentation of ``plumber`` for detailed information about the
        plumbing system.
        
        
        Attributes
        ~~~~~~~~~~
        
        While it is not strictly necessary, it's a good idea to separate the
        hierarchical structure of a model from the node related attributes to avoid
        naming conflicts. Attributes are provided via ``node.behaviors.Attributes``
        plumbing behavior:
        
        .. code-block:: python
        
            from node.behaviors import Attributes
            from node.behaviors import DefaultInit
            from node.behaviors import DictStorage
            from node.behaviors import MappingNode
            from plumber import plumbing
        
            @plumbing(
                Attributes,
                DefaultInit,
                MappingNode,
                DictStorage)
            class NodeWithAttributes:
                pass
        
        The node now provides an ``attrs`` attribute. Node attributes are itself just
        a node:
        
        .. code-block:: pycon
        
            >>> node = NodeWithAttributes()
            >>> attrs = node.attrs
            >>> attrs
            <NodeAttributes object 'None' at ...>
        
            >>> attrs['foo'] = 'foo'
        
        If it's desired to access attribute members via python attribute access,
        ``attribute_access_for_attrs`` must be set on node:
        
        .. code-block:: pycon
        
            >>> node.attribute_access_for_attrs = True
            >>> attrs = node.attrs
            >>> attrs.foo = 'bar'
            >>> attrs.foo
            'bar'
        
        A custom attributes implementation can be set by defining
        ``attributes_factory`` on the node:
        
        .. code-block:: python
        
            from node.behaviors import NodeAttributes
        
            class CustomAttributes(NodeAttributes):
                pass
        
            class CustomAttributesNode(NodeWithAttributes):
                attributes_factory = CustomAttributes
        
        This factory is then used to instantiate the attributes:
        
        .. code-block:: pycon
        
            >>> node = CustomAttributesNode()
            >>> node.attrs
            <CustomAttributes object 'None' at ...>
        
        
        Schema
        ~~~~~~
        
        To describe the data types of node members, this package provides a mechanism
        for defining schemata.
        
        This can happen in different ways. One is to define the schema for node members
        directly. This is useful for nodes representing a leaf in the hierarchy or for
        node attribute nodes:
        
        .. code-block:: python
        
            from node import schema
            from node.base import BaseNode
            from node.behaviors import DefaultInit
            from node.behaviors import DictStorage
            from node.behaviors import MappingNode
            from node.behaviors import Schema
            from plumber import plumbing
        
            @plumbing(
                DefaultInit,
                MappingNode,
                DictStorage,
                Schema)
            class SchemaNode:
                schema = {
                    'int': schema.Int(),
                    'float': schema.Float(default=1.),
                    'str': schema.Str(),
                    'bool': schema.Bool(default=False),
                    'node': schema.Node(BaseNode)
                }
        
        Children defined in the schema provide a default value. If not explicitely
        defined, the default value is always ``node.utils.UNSET``:
        
        .. code-block:: pycon
        
            >>> node = SchemaNode()
            >>> node['int']
            <UNSET>
        
            >>> node['float']
            1.0
        
            >>> node['bool']
            False
        
        Children defined in the schema are validated against the defined type when
        setting it's value:
        
        .. code-block:: pycon
        
            >>> node = SchemaNode()
            >>> node['int'] = 'A'
            Traceback (most recent call last):
              ...
            ValueError: A is no <class 'int'> type
        
        For accessing members defined in the schema as node attributes,
        ``SchemaAsAttributes`` plumbing behavior can be used:
        
        .. code-block:: python
        
            from node.behaviors import SchemaAsAttributes
        
            @plumbing(SchemaAsAttributes)
            class SchemaAsAttributesNode(BaseNode):
                schema = {
                    'int': schema.Int(default=1),
                }
        
        Node ``attrs`` now provides access to the schema members:
        
        .. code-block:: pycon
        
            >>> node = SchemaAsAttributesNode()
            >>> node.attrs['int']
            1
        
        Schema members can also be defined as class attributes. This is syntactically
        the most elegant way, but comes with the tradeoff of possible naming conflicts:
        
        .. code-block:: python
        
            from node.behaviors import SchemaProperties
        
            @plumbing(
                DefaultInit,
                MappingNode,
                DictStorage,
                SchemaProperties)
            class SchemaPropertiesNode:
                text = schema.Str(default='Text')
        
        Here we access ``text`` as class attribute:
        
        .. code-block:: pycon
        
            >>> node = SchemaPropertiesNode()
            >>> node.text
            'Text'
        
            >>> node.text = 1
            Traceback (most recent call last):
              ...
            ValueError: 1 is no <class 'str'> type
        
        
        Plumbing Behaviors
        ------------------
        
        General Behaviors
        ~~~~~~~~~~~~~~~~~
        
        **node.behaviors.DefaultInit**
            Plumbing behavior providing default ``__init__`` function on node. This
            behavior is going to be deprecated in future versions. Use
            ``node.behaviors.NodeInit`` instead.
            See ``node.interfaces.IDefaultInit``.
        
        **node.behaviors.NodeInit**
            Plumbing behavior for transparent setting of ``__name__`` and ``__parent__``
            at object initialization time.
            See ``node.interfaces.INodeInit``.
        
        **node.behaviors.Node**
            Fill in gaps for full INode API. See ``node.interfaces.INode``.
        
        **node.behaviors.ContentishNode**
            A node which can contain children. See
            ``node.interfaces.IContentishNode``. Concrete implementations are
            ``node.behaviors.MappingNode`` and ``node.behaviors.SequenceNode``.
        
        **node.behaviors.Attributes**
            Provide attributes on node. See ``node.interfaces.IAttributes``. If
            ``node.behaviors.Nodespaces`` is applied on node, the attributes instance
            gets stored internally in ``__attrs__`` nodespace, otherwise its set on
            ``__attrs__`` attribute.
        
        **node.behaviors.Events**
            Provide an event registration and dispatching mechanism.
            See ``node.interfaces.IEvents``.
        
        **node.behaviors.BoundContext**
            Mechanism for scoping objects to interfaces and classes.
            See ``node.interfaces.IBoundContext``.
        
        **node.behaviors.NodeReference**
            Plumbing behavior holding an index of nodes contained in the tree.
            See ``node.interfaces.INodeReference``.
        
        **node.behaviors.WildcardFactory**
            Plumbing behavior providing factories by wildcard patterns.
            See ``node.interfaces.IWildcardFactory``.
        
        
        Mapping Behaviors
        ~~~~~~~~~~~~~~~~~
        
        **node.behaviors.MappingNode**
            Turn an object into a mapping node. Extends ``node.behaviors.Node``.
            See ``node.interfaces.IMappingNode``.
        
        **node.behaviors.MappingAdopt**
            Plumbing behavior that provides ``__name__`` and ``__parent__`` attribute
            adoption on child nodes of mapping.
            See ``node.interfaces.IMappingAdopt``.
        
        **node.behaviors.MappingConstraints**
            Plumbing behavior for constraints on mapping nodes.
            See ``node.interfaces.IMappingConstraints``.
        
        **node.behaviors.UnicodeAware**
            Plumbing behavior to ensure unicode for keys and string values.
            See ``node.interfaces.IUnicodeAware``.
        
        **node.behaviors.Alias**
            Plumbing behavior that provides aliasing of child keys.
            See ``node.interfaces.IAlias``.
        
        **node.behaviors.AsAttrAccess**
            Plumbing behavior to get node as IAttributeAccess implementation.
            See ``node.interfaces.IAsAttrAccess``.
        
        **node.behaviors.ChildFactory**
            Plumbing behavior providing child factories.
            See ``node.interfaces.IChildFactory``.
        
        **node.behaviors.FixedChildren**
            Plumbing Behavior that initializes a fixed dictionary as children.
            See ``node.interfaces.IFixedChildren``.
        
        **node.behaviors.Nodespaces**
            Plumbing behavior for providing nodespaces on node.
            See ``node.interfaces.INodespaces``.
        
        **node.behaviors.Lifecycle**
            Plumbing behavior taking care of lifecycle events.
            See ``node.interfaces.ILifecycle``.
        
        **node.behaviors.AttributesLifecycle**
            Plumbing behavior for handling lifecycle events on attribute manipulation.
            See ``node.interfaces.IAttributesLifecycle``.
        
        **node.behaviors.Invalidate**
            Plumbing behavior for node invalidation.
            See ``node.interfaces.Invalidate``.
        
        **node.behaviors.VolatileStorageInvalidate**
            Plumbing behavior for invalidating nodes using a volatile storage.
            See ``node.interfaces.Invalidate``.
        
        **node.behaviors.Cache**
            Plumbing behavior for caching.
            See ``node.interfaces.ICache``.
        
        **node.behaviors.MappingOrder**
            Plumbing behavior for ordering support on mapping nodes.
            See ``node.interfaces.IMappingOrder``.
        
        **node.behaviors.UUIDAware**
            Plumbing behavior providing a uuid on nodes.
            See ``node.interfaces.IUUIDAware``.
        
        **node.behaviors.MappingReference**
            Plumbing behavior to provide ``node.interfaces.INodeReference`` on mapping
            nodes. See ``node.interfaces.IMappingReference``.
        
        **node.behaviors.MappingStorage**
            Provide abstract mapping storage access.
            See ``node.interfaces.IMappingStorage``.
        
        **node.behaviors.DictStorage**
            Provide dictionary storage. Extends ``node.behaviors.MappingStorage``.
            See ``node.interfaces.IMappingStorage``.
        
        **node.behaviors.OdictStorage**
            Provide ordered dictionary storage. Extends
            ``node.behaviors.MappingStorage``. See ``node.interfaces.IMappingStorage``.
        
        **node.behaviors.Fallback**
            Provide a way to fall back to values by subpath stored on another node.
            See ``node.interfaces.IFallback``.
        
        **node.behaviors.Schema**
            Provide schema validation and value serialization on node values.
            See ``node.interfaces.ISchema``.
        
        **node.behaviors.SchemaAsAttributes**
            Provide schema validation and value serialization on node values via
            dedicated attributes object.
            See ``node.interfaces.ISchemaAsAttributes``.
        
        **node.behaviors.SchemaProperties**
            Provide schema fields as class properties.
            See ``node.interfaces.ISchemaProperties``.
        
        **node.behaviors.MappingFilter**
            Filter mapping children by class or interface.
            See ``node.interfaces.IChildFilter``.
        
        
        Sequence Behaviors
        ~~~~~~~~~~~~~~~~~~
        
        **node.behaviors.SequenceNode**
            Turn an object into a sequence node. Extends ``node.behaviors.Node``.
            See ``node.interfaces.IMappingNode``.
        
        **node.behaviors.SequenceAdopt**
            Plumbing behavior that provides ``__name__`` and ``__parent__`` attribute
            adoption on child nodes of sequence.
            See ``node.interfaces.ISequenceAdopt``.
        
        **node.behaviors.SequenceConstraints**
            Plumbing behavior for constraints on sequence nodes.
            See ``node.interfaces.ISequenceConstraints``.
        
        **node.behaviors.SequenceStorage**
            Provide abstract sequence storage access.
            See ``node.interfaces.ISequenceStorage``.
        
        **node.behaviors.ListStorage**
            Provide list storage. See ``node.interfaces.ISequenceStorage``.
        
        **node.behaviors.SequenceReference**
            Plumbing behavior to provide ``node.interfaces.INodeReference`` on sequence
            nodes. See ``node.interfaces.ISequenceReference``.
        
        **node.behaviors.SequenceFilter**
            Filter sequence children by class or interface.
            See ``node.interfaces.IChildFilter``.
        
        **node.behaviors.SequenceOrder**
            Plumbing behavior for ordering support on sequence nodes.
            See ``node.interfaces.ISequenceOrder``.
        
        
        JSON Serialization
        ------------------
        
        Nodes can be serialized to and deserialized from JSON:
        
        .. code-block:: pycon
        
            >>> from node.serializer import serialize
            >>> json_dump = serialize(BaseNode(name='node'))
        
            >>> from node.serializer import deserialize
            >>> deserialize(json_dump)
            <BaseNode object 'node' at ...>
        
        For details on serialization API please read file in
        ``docs/archive/serializer.rst``.
        
        
        Python Versions
        ---------------
        
        - Python 2.7, 3.7+
        - May work with other versions (untested)
        
        
        Contributors
        ============
        
        - Robert Niederreiter
        - Florian Friesdorf
        - Jens Klein
        
        
        
        Changes
        =======
        
        1.2 (2022-12-05)
        ----------------
        
        - Do not overwrite ``uuid`` in ``node.behaviors.UUIDAware.__init__`` if
          ``uuid`` already set.
          [rnix]
        
        - Rename ``node.interfaces.IOrder`` to ``node.interfaces.IMappingOrder``
          and ``node.behaviors.Order`` to ``node.behaviors.MappingOrder``.
          B/C is kept.
          [rnix]
        
        - Introduce ``node.behaviors.ISequenceOrder`` and
          ``node.interfaces.SequenceOrder``.
          [rnix]
        
        - Introduce ``node.interfaces.INodeOrder``. Used as base for
          ``node.interfaces.IMappingOrder`` and ``node.interfaces.ISequenceOrder``.
          [rnix]
        
        - Add rich comparison functions ``__lt__``, ``__le__``, ``__gt__`` and
          ``__ge__`` to ``node.utils.Unset``.
          [rnix]
        
        **Breaking changes**:
        
        - Importing B/C ``Order`` behavior from ``node.behaviors.order``
          not works any more. Please import from ``node.behaviors``.
          [rnix]
        
        
        1.1 (2022-10-06)
        ----------------
        
        - Add ``node.schema.DateTime``, ``node.schema.DateTimeSerializer`` and
          ``node.schema.datetime_serializer``.
          [rnix]
        
        - Subclass ``threading.local`` for
          ``node.behaviors.lifecycle._lifecycle_context``,
          ``node.behaviors.events._attribute_subscribers`` and
          ``node.behaviors.schema._schema_property`` objects in order to safely provide
          default values.
          [rnix]
        
        - Introduce ``node.interfaces.IChildFilter``, ``node.behaviors.MappingFilter``
          and ``node.behaviors.SequenceFilter``.
          [rnix]
        
        - Introduce ``node.interfaces.IWildcardFactory`` and
          ``node.behaviors.WildcardFactory``.
          [rnix]
        
        - Introduce ``node.interfaces.INodeInit`` and ``node.behaviors.NodeInit``.
          [rnix]
        
        - Deprecate ``IFixedChildren.fixed_children_factories`` Use
          ``IFixedChildren.factories`` instead.
          [rnix]
        
        - Introduce ``node.interfaces.IContentishNode`` and
          ``node.behaviors.ContentishNode``. Use as base for mapping and sequence nodes.
          [rnix]
        
        - ``insertbefore``, ``insertafter`` and ``swap`` in ``node.behaviors.Order``
          alternatively accept node names as arguments where possible.
          [rnix]
        
        - ``insertbefore``, ``insertafter``, and ``insertfirst`` and ``insertlast`` in
          ``node.behaviors.Order`` internally use ``movebefore``, ``moveafter``,
          ``movefirst`` and ``movelast`` of ``odict`` to avoid modifying the data
          structure before ``__setitem__`` gets called.
          [rnix]
        
        - Extend ``node.interfaces.IOrder``  respective ``node.behaviors.Order``
          by ``movebefore``, ``moveafter``, ``movefirst`` and ``movelast``.
          [rnix]
        
        - Reset ``__parent__`` in ``node.behaviors.Node.detach``. Node is no longer
          contained in tree.
          [rnix]
        
        - Introduce ``IndexViolationError`` which inherits from ``ValueError`` and
          raise it in reference related behaviors instead of ``ValueError`` where
          appropriate.
          [rnix]
        
        - Introduce ``node.interfaces.INodeReference`` and
          ``node.behaviors.NodeReference``.
          [rnix]
        
        - Introduce ``node.interfaces.ISequenceReference`` and
          ``node.behaviors.SequenceReference``.
          [rnix]
        
        - Rename ``node.interfaces.IReference`` to ``node.interfaces.IMappingReference``
          and ``node.behaviors.Reference`` to ``node.behaviors.MappingReference``.
          B/C is kept.
          [rnix]
        
        **Breaking changes**:
        
        - Remove ``_notify_suppress`` flag from ``Lifecycle`` behavior. Introduce
          ``suppress_lifecycle_events`` contextmanager as substitute.
          [rnix]
        
        - Importing ``ChildFactory`` and ``FixedChildren`` from
          ``node.behaviors.common`` not works any more. Please import from
          ``node.behaviors``.
          [rnix]
        
        - Importing B/C ``Reference`` behavior from ``node.behaviors.reference``
          not works any more. Please import from ``node.behaviors``.
          [rnix]
        
        
        1.0 (2022-03-17)
        ----------------
        
        - Implement ``__copy__`` and ``__deepcopy__`` on ``node.utils.UNSET``.
          [rnix]
        
        - Introduce ``node.interfaces.ISequenceConstraints`` and
          ``node.behaviors.SequenceConstraints``.
          [rnix]
        
        - Rename ``node.interfaces.INodeChildValidate`` to
          ``node.interfaces.IMappingConstraints`` and
          ``node.behaviors.NodeChildValidate`` to ``node.behaviors.MappingConstraints``.
          ``MappingConstraints`` implementation moved from ``node.behaviors.common`` to
          ``node.behaviors.constraints``. B/C is kept.
          [rnix]
        
        - Introduce ``node.interfaces.ISequenceAdopt`` and
          ``node.behaviors.SequenceAdopt``.
          [rnix]
        
        - ``MappingAdopt`` now catches all exceptions instead of only
          ``AttributeError``, ``KeyError`` and ``ValueError``.
          [rnix]
        
        - Rename ``node.interfaces.IAdopt`` to ``node.interfaces.IMappingAdopt`` and
          ``node.behaviors.Adopt`` to ``node.behaviors.MappingAdopt``. ``MappingAdopt``
          implementation moved from ``node.behaviors.common`` to
          ``node.behaviors.adopt``. B/C is kept.
          [rnix]
        
        - ``node.behaviors.Attributes`` now also works if
          ``node.behaviors.Nodespaces`` is not applied.
          [rnix]
        
        - Introduce ``node.behaviors.Node`` which implements only
          ``node.interfaces.INode`` contract. It is used as base for
          ``node.behaviors.MappingNode`` and ``node.behaviors.SequcneNode``.
          [rnix]
        
        - Do not inherit ``node.interfaces.INode`` from
          ``zope.interfaces.common.mapping.IFullMapping`` any more. Data model specific
          interfaces are added now via ``node.interfaces.IMappingNode`` and
          ``node.interfaces.ISequenceNode``.
          [rnix]
        
        - Introduce sequence nodes. Sequence nodes are implemented via
          ``node.behaviors.SequcneNode`` and ``node.behaviors.ListStorage``.
          [rnix]
        
        - Rename ``node.interfaces.INodify`` to ``node.interfaces.IMappingNode`` and
          ``node.behaviors.Nodify`` to ``node.behaviors.MappingNode``. ``MappingNode``
          implementation moved from ``node.behaviors.nodify`` to
          ``node.behaviors.mapping``. B/C is kept.
          [rnix]
        
        - Rename ``node.interfaces.IStorage`` to ``node.interfaces.IMappingStorage``
          and ``node.behaviors.Storage`` to ``node.behaviors.Storage``. B/C is kept.
          [rnix]
        
        - Add key and value type validation to schema fields where appropriate.
          [rnix]
        
        - Introduce serializer support to schema fields. Add a couple of concrete field
          serializer implementations to ``node.schema.serializer``.
          [rnix]
        
        - Add ``ODict`` and ``Node`` schema fields to ``node.schema.fields``.
          [rnix]
        
        - Add ``node.schema.fields.IterableField`` and use as base class for
          ``List``, ``Tuple`` and ``Set`` schema fields.
        
        - Introduce ``node.behaviors.schema.SchemaProperties`` plumbing behavior.
          [rnix]
        
        - Split up ``node.schema`` module into a package.
          [rnix]
        
        - Introduce ``node.behaviors.context.BoundContext`` plumbing behavior.
          [rnix]
        
        **Breaking changes**:
        
        - Remove ``node.behaviors.GetattrChildren``. See ``node.utils.AttributeAccess``
          instead if you need to access node children via ``__getattr__``.
          [rnix]
        
        - Importing B/C ``Adopt`` behavior from ``node.behaviors.common``
          not works any more. Please import from ``node.behaviors``.
          [rnix]
        
        - Importing B/C ``NodeChildValidate`` behavior from ``node.behaviors.common``
          not works any more. Please import from ``node.behaviors``.
          [rnix]
        
        - Importing B/C ``Nodify`` behavior from ``node.behaviors.nodify``
          not works any more. Please import from ``node.behaviors``.
          [rnix]
        
        - Remove deprecated B/C import location ``node.parts``.
          [rnix]
        
        - ``node.behaviors.schema.Schema`` no longer considers wildcard fields.
          [rnix]
        
        - ``node.behaviors.schema.Schema.__setitem__`` deletes value from related
          storage for field if value is ``node.utils.UNSET``.
          [rnix]
        
        - ``node.behaviors.schema.Schema.__getitem__`` always returns default value for
          field instead of raising ``KeyError`` if no default is set.
          [rnix]
        
        - Default value of ``node.schema.fields.Field.default`` is ``node.utils.UNSET``
          now.
          [rnix]
        
        - ``node.schema.fields.Field.validate`` raises exception if validation fails
          instead of returning boolean.
          [rnix]
        
        
        0.9.28 (2021-11-08)
        -------------------
        
        - Add missing ``node.interfaces.INodeAttributes`` interface.
          [rnix]
        
        - Add missing ``attribute_access_for_attrs`` attribute to ``IAttributes``
          interface.
          [rnix]
        
        - Rename ``node.behaviors.common.NodeChildValidate.allow_non_node_childs``
          to ``allow_non_node_children``. A Deprecation warning is printed if the
          old attribute is used.
          [rnix]
        
        - Introduce ``node.behaviors.schema.Schema``,
          ``node.behaviors.schema.SchemaAsAttributes`` and related schema definitions
          in ``node.schema``.
          [rnix]
        
        
        0.9.27 (2021-10-21)
        -------------------
        
        - Expose ``first_key``, ``last_key``, ``next_key`` and ``prev_key`` from
          odict storage on ``Order`` behavior.
          [rnix, 2021-10-21]
        
        - Add basic serializer settings mechanism.
          [rnix, 2021-07-20]
        
        
        0.9.26 (2021-05-10)
        -------------------
        
        - Use ``node.utils.safe_decode`` in ``node.behaviors.nodify.Nodify.treerepr``.
          [rnix, 2021-05-04]
        
        - Add ``node.utils.safe_encode`` and ``node.utils.safe_decode``.
          [rnix, 2021-05-04]
        
        
        0.9.25 (2020-03-30)
        -------------------
        
        - Introduce ``uuid_factory`` function on ``node.interfaces.IUUIDAware`` and
          implement default function in ``node.behaviors.common.UUIDAware``.
          [rnix, 2020-03-01]
        
        - Rename ``NodeTestCase.expect_error`` to ``NodeTestCase.expectError``.
          [rnix, 2019-09-04]
        
        - Rename ``NodeTestCase.check_output`` to ``NodeTestCase.checkOutput``.
          [rnix, 2019-09-04]
        
        - Introduce ``prefix`` keyword argument in ``Nodify.treerepr``.
          [rnix, 2019-09-04]
        
        
        0.9.24 (2019-07-10)
        -------------------
        
        - Overhaul ``node.behaviors.Order``. Use related functions from ``odict`` where
          appropriate.
          [rnix, 2019-07-10]
        
        - Remove superfluous ``extra_require`` from ``setup.py``.
          [rnix, 2019-04-25]
        
        - Drop Support for python < 2.7 and < 3.3.
          [rnix, 2019-04-25]
        
        
        0.9.23 (2018-11-07)
        -------------------
        
        - Use property decorators for ``node.behaviors.reference.Reference.uuid``.
          [rnix, 2017-12-15]
        
        
        0.9.22 (2017-07-18)
        -------------------
        
        - Add ``always_dispatch`` keyword argument to
          ``node.behaviors.events.EventAttribute`` constructor which defines whether
          events are always dispatched on ``__set__``, not only if attribute value
          changes.
          [rnix, 2017-06-20]
        
        - Use ``node.utils.UNSET`` as default ``default`` value in
          ``node.behaviors.events.EventAttribute.__init__``.
          [rnix, 2017-06-19]
        
        - Introduce ``node.behaviors.events.EventAttribute.subscriber`` decorator which
          can be used to register attribute subscribers.
          [rnix, 2017-06-19]
        
        - Move event dispatching related classes and functions from ``node.events``
          to ``node.behaviors.events`` and import it from there in ``node.events``.
          [rnix, 2017-06-16]
        
        - Introduce ``node.interfaces.IEvents`` and implement
          ``node.behaviors.events.Events`` behavior. Contains business logic from
          ``node.events.EventDispatcher``. Use new behavior on ``EventDispatcher``.
          [rnix, 2017-06-16]
        
        - Create ``suppress_events`` context manager which can be used to
          suppress event notification in conjunction with ``node.behaviors.Events``
          behavior.
          [rnix, 2017-06-15]
        
        - Create ``node.behaviors.fallback.fallback_processing`` context manager and
          and use it in ``node.behaviors.fallback.Fallback.__getitem__`` to check
          whether fallback processing is active.
          [rnix, 2017-06-15]
        
        
        0.9.21 (2017-06-15)
        -------------------
        
        - Introduce ``node.events.EventDispatcher`` and ``node.events.EventAttribute``.
          [rnix, 2017-06-15]
        
        - Use ``setattr`` in ``instance_property`` decorator instead of
          ``object.__setattr__`` in order to avoid errors with custom low level
          ``__setattr__`` implementations.
          [rnix, 2017-06-14]
        
        
        0.9.20 (2017-06-07)
        -------------------
        
        - Type cast sort key to ``node.compat.UNICODE_TYPE`` in
          ``node.behaviors.Nodify.treerepr`` to avoid unicode decode errors.
          [rnix, 2017-06-07]
        
        
        0.9.19 (2017-06-07)
        -------------------
        
        - Python 3 and pypy compatibility.
          [rnix, 2017-06-02]
        
        - Drop support for Python < 2.7.
          [rnix, 2017-06-02]
        
        - Add ``__bool__`` to ``node.behaviors.Nodify``.
          [rnix, 2017-06-02]
        
        - Add ``__bool__`` to ``node.utils.UNSET``.
          [rnix, 2017-06-02]
        
        - Add ``treerepr`` in ``node.behaviors.nodify.Nodify`` and move code from
          ``printtree`` to it. Returs tree representation as string instead of printing
          it. ``printtree`` uses ``treerepr`` now. As enhancement ``treerepr`` sorts
          children of node if it does not implement ``IOrdered`` in order to ensure
          consistend output which can be used to write tests against.
          [rnix, 2017-06-02]
        
        - Use ``object.__getattribute__`` explicitely in
          ``node.utils.instance_property`` to check whether property value already has
          been computed in order to avoid problems when oberwriting ``__getattr__``
          on classes using ``instance_property`` decorator.
          [rnix, 2017-06-02]
        
        
        0.9.18.1 (2017-02-23)
        ---------------------
        
        - Fix permissions.
          [rnix, 2017-02-23]
        
        
        0.9.18 (2017-02-14)
        -------------------
        
        - Add ``node.utils.node_by_path``.
          [rnix, 2017-02-07]
        
        - Do not depend on ``unittest2`` since its is not used.
          [jensens, 2017-01-17]
        
        - Add ``node.behaviors.Fallback`` behavior.
          [jensens, 2017-01-17]
        
        
        0.9.17 (2017-01-17)
        -------------------
        
        - Add basic JSON serializer and deserializer.
          [rnix, 2016-12-03]
        
        
        0.9.16 (2015-10-08)
        -------------------
        
        - Only encode name in ``node.behaviors.nodify.Nodify.__repr__`` and
          ``node.behaviors.nodify.Nodify.noderepr`` if name is unicode instance.
          [rnix, 2015-10-03]
        
        - Improve ``node.behaviors.nodify.Nodify.printtree``. None node children are
          printed with key.
          [rnix, 2015-10-03]
        
        
        0.9.15 (2014-12-17)
        -------------------
        
        - Fix dependency declaration to ``odict`` in order to make setuptools 8.x+
          happy; using ``>=`` instead of ``>`` now.
          [jensens, 2014-12-17]
        
        
        0.9.14
        ------
        
        - use ``plumbing`` decorator instead of ``plumber`` metaclass.
          [rnix, 2014-07-31]
        
        
        0.9.13
        ------
        
        - Introduce ``node.behaviors.cache.VolatileStorageInvalidate``.
          [rnix, 2014-01-15]
        
        
        0.9.12
        ------
        
        - Add ``zope.component`` to install dependencies.
          [rnix, 2013-12-09]
        
        
        0.9.11
        ------
        
        - Use ``node.utils.UNSET`` instance in
          ``node.behaviors.mapping.ExtendedWriteMapping.pop``.
          [rnix, 2013-02-10]
        
        - Improve ``node.utils.Unset``. Add ``Unset`` instance at
          ``node.utils.UNSET``.
          [rnix, 2013-02-10]
        
        
        0.9.10
        ------
        
        - Fix ``node.utils.StrCodec.encode`` to return value as is if str and decoding
          failed.
          [rnix, 2012-11-07]
        
        
        0.9.9
        -----
        
        - Python 2.7 compatibility.
          [rnix, 2012-10-15]
        
        - Remove ``zope.component.event`` B/C.
          [rnix, 2012-10-15]
        
        - Remove ``zope.location`` B/C.
          [rnix, 2012-10-15]
        
        - Remove ``zope.lifecycleevent`` B/C.
          [rnix, 2012-10-15]
        
        - Pep8.
          [rnix, 2012-10-15]
        
        
        0.9.8
        -----
        
        - Deprecate the use of ``node.parts``. Use ``node.behaviors`` instead.
          [rnix, 2012-07-28]
        
        - Adopt to ``plumber`` 1.2
          [rnix, 2012-07-28]
        
        
        0.9.7
        -----
        
        - Introduce ``node.interfaces.IOrdered`` Marker interface. Set this interface
          on ``node.parts.storage.OdictStorage``.
          [rnix, 2012-05-21]
        
        - ``node.parts.mapping.ClonableMapping`` now supports ``deepcopy``.
          [rnix, 2012-05-18]
        
        - Use ``zope.interface.implementer`` instead of ``zope.interface.implements``
          all over the place.
          [rnix, 2012-05-18]
        
        - Remove superfluos interfaces.
          [rnix, 2012-05-18]
        
        - Remove ``Zodict`` from ``node.utils``.
          [rnix, 2012-05-18]
        
        - Remove ``AliasedNodespace``, use ``Alias`` part instead.
          [rnix, 2012-05-18]
        
        - Move aliaser objects from ``node.aliasing`` to ``node.parts.alias``.
          [rnix, 2012-05-18]
        
        - Remove ``composition`` module.
          [rnix, 2012-05-18]
        
        - Remove ``bbb`` module.
          [rnix, 2012-05-18]
        
        
        0.9.6
        -----
        
        - Do not inherit ``node.parts.Reference`` from ``node.parts.UUIDAware``.
          [rnix, 2012-01-30]
        
        - Set ``uuid`` in ``node.parts.Reference.__init__`` plumb.
          [rnix, 2012-01-30]
        
        
        0.9.5
        -----
        
        - add ``node.parts.nodify.Nodify.acquire`` function.
          [rnix, 2011-12-05]
        
        - add ``node.parts.ChildFactory`` plumbing part.
          [rnix, 2011-12-04]
        
        - add ``node.parts.UUIDAware`` plumbing part.
          [rnix, 2011-12-02]
        
        - fix ``node.parts.Order.swap`` in order to work with pickled nodes.
          [rnix, 2011-11-28]
        
        - use ``node.name`` instead of ``node.__name__`` in
          ``node.parts.nodify.Nodify.path``.
          [rnix, 2011-11-17]
        
        - add ``swap`` to  ``node.parts.Order``.
          [rnix, 2011-10-05]
        
        - add ``insertfirst`` and ``insertlast`` to ``node.parts.Order``.
          [rnix, 2011-10-02]
        
        
        0.9.4
        -----
        
        - add ``node.utils.debug`` decorator.
          [rnix, 2011-07-23]
        
        - remove non storage contract specific properties from
          ``node.aliasing.AliasedNodespace``
          [rnix, 2011-07-18]
        
        - ``node.aliasing`` test completion
          [rnix, 2011-07-18]
        
        - Add non strict functionality to ``node.aliasing.DictAliaser`` for accessing
          non aliased keys as is as fallback
          [rnix, 2011-07-18]
        
        - Consider ``INode`` implementing objects in ``node.utils.StrCodec``
          [rnix, 2011-07-16]
        
        - Remove duplicate implements in storage parts
          [rnix, 2011-05-16]
        
        
        0.9.3
        -----
        
        - Increase test coverage
          [rnix, 2011-05-09]
        
        - Add interfaces ``IFixedChildren`` and ``IGetattrChildren`` for related parts.
          [rnix, 2011-05-09]
        
        - Rename ``Unicode`` part to ``UnicodeAware``.
          [rnix, 2011-05-09]
        
        - Add ``node.utils.StrCodec``.
          [rnix, 2011-05-09]
        
        - Inherit ``INodify`` interface from ``INode``.
          [rnix, 2011-05-08]
        
        - Locking tests. Add ``time.sleep`` after thread start.
          [rnix, 2011-05-08]
        
        - Cleanup ``BaseTester``, remove ``sorted_output`` flag (always sort), also
          search class bases for detection in ``wherefrom``.
          [rnix, 2011-05-08]
        
        - Remove useless try/except in ``utils.AttributeAccess``.
          [rnix, 2011-05-08]
        
        - Add ``instance_property`` decorator to utils.
          [rnix, 2011-05-06]
        
        - Add ``FixedChildren`` and ``GetattrChildren`` parts.
          [chaoflow, 2011-04-22]
        
        
        0.9.2
        -----
        
        - Add ``__nonzero__`` on ``Nodifiy`` part always return True.
          [rnix, 2011-03-15]
        
        
        0.9.1
        -----
        
        - Provide ``node.base.Node`` with same behavior like ``zodict.Node`` for
          migration purposes.
          [rnix, 2011-02-08]
        
        
        0.9
        ---
        
        - Make it work [rnix, chaoflow, et al]
        
        
        License
        =======
        
        Copyright (c) 2009-2021, BlueDynamics Alliance, Austria
        Copyright (c) 2021-2022, Node Contributors
        All rights reserved.
        
        Redistribution and use in source and binary forms, with or without
        modification, are permitted provided that the following conditions are met:
        
        * Redistributions of source code must retain the above copyright notice, this
          list of conditions and the following disclaimer.
        
        * Redistributions in binary form must reproduce the above copyright notice, this
          list of conditions and the following disclaimer in the documentation and/or
          other materials provided with the distribution.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
        ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
        ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
        LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
        ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
        SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        
Keywords: node tree fullmapping dict
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: BSD License
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
