node


Namenode JSON
Version 1.2.1 PyPI version JSON
download
home_pagehttp://github.com/conestack/node
SummaryBuilding data structures as node trees
upload_time2023-04-16 06:08:08
maintainer
docs_urlNone
authorNode Contributors
requires_python
licenseSimplified BSD
keywords node tree fullmapping dict
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            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.1 (2023-04-16)
------------------

- Replace deprecated import of ``Order`` with ``MappingOrder`` in ``node.base``.
  [rnix]


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.

            

Raw data

            {
    "_id": null,
    "home_page": "http://github.com/conestack/node",
    "name": "node",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "node tree fullmapping dict",
    "author": "Node Contributors",
    "author_email": "dev@conestack.org",
    "download_url": "https://files.pythonhosted.org/packages/eb/63/d2c9820b2dbf098c9d410162aa99347f6e06ad7813ded994f18993f67def/node-1.2.1.tar.gz",
    "platform": null,
    "description": "Node\n====\n\n.. image:: https://img.shields.io/pypi/v/node.svg\n    :target: https://pypi.python.org/pypi/node\n    :alt: Latest PyPI version\n\n.. image:: https://img.shields.io/pypi/dm/node.svg\n    :target: https://pypi.python.org/pypi/node\n    :alt: Number of PyPI downloads\n\n.. image:: https://github.com/conestack/node/actions/workflows/test.yaml/badge.svg\n    :target: https://github.com/conestack/node/actions/workflows/test.yaml\n    :alt: Test node\n\n\nOverview\n--------\n\nNode is a library to create nested data models and structures.\n\nThese data models are described as trees of nodes, optionally with attributes\nand schema definitions.\n\nThey utilize:\n\n- Python's\n  `mapping and sequence API's <http://docs.python.org/reference/datamodel.html>`_\n  for accessing node members.\n- The contract of\n  `zope.location.interfaces.ILocation <https://zopelocation.readthedocs.io/en/latest/api.html#zope.location.interfaces.ILocation>`_\n  for hierarchy information.\n\nOne purpose of this package is to provide a unified API to different backend\nstorages. Specific storage related implementations are for example:\n\n- `node.ext.fs <https://pypi.org/project/node.ext.fs>`_\n- `node.ext.ldap <https://pypi.org/project/node.ext.ldap>`_\n- `node.ext.yaml <https://pypi.org/project/node.ext.yaml>`_\n- `node.ext.zodb <https://pypi.org/project/node.ext.zodb>`_\n\nAnother usecase is providing interfaces for specific application domains.\n\nE.g. for user and group management,\n`node.ext.ugm <https://pypi.org/project/node.ext.ugm>`_ defines the interfaces.\nAdditional it implements a file based default implementation. Then there are\nspecific implementations of those interfaces in\n`node.ext.ldap <https://pypi.org/project/node.ext.ldap>`_ and\n`cone.sql <https://pypi.org/project/cone.sql>`_, to access users and groups in\nLDAP and SQL databases.\n\nThis package is also used to build in-memory models of all sorts.\n\nE.g.  `yafowil <https://pypi.org/project/yafowil>`_ is a HTML form processing\nand rendering library. It uses node trees for declarative description of the\nform model.\n\nAnother one to mention is `cone.app <https://pypi.org/project/cone.app>`_,\na `Pyramid <https://pypi.org/project/pyramid>`_ based development environment\nfor web applications, which uses node trees to describe the application model.\n\n\nBasic Usage\n-----------\n\nThere are two basic node types. Mapping nodes and sequence nodes. This\npackage provides some basic nodes to start from.\n\n\nMapping Nodes\n~~~~~~~~~~~~~\n\nMapping nodes implement ``node.interfaces.IMappingNode``. A mapping in python\nis a container object that supports arbitrary key lookups and implements the\nmethods specified in the ``MutableMapping`` of pythons abstract base classes\nrespective ``zope.interface.common.mapping.IFullMapping``.\n\nAn unordered node. This can be used as base for trees where order of items\ndoesn't matter:\n\n.. code-block:: python\n\n    from node.base import BaseNode\n\n    root = BaseNode(name='root')\n    root['child'] = BaseNode()\n\nAn ordered node. The order of items is preserved:\n\n.. code-block:: python\n\n    from node.base import OrderedNode\n\n    root = OrderedNode(name='orderedroot')\n    root['foo'] = OrderedNode()\n    root['bar'] = OrderedNode()\n\nWith ``printtree`` we can do a quick inspection of our node tree:\n\n.. code-block:: pycon\n\n    >>> root.printtree()\n    <class 'node.base.OrderedNode'>: orderedroot\n      <class 'node.base.OrderedNode'>: foo\n      <class 'node.base.OrderedNode'>: bar\n\n\nSequence Nodes\n~~~~~~~~~~~~~~\n\nSequence nodes implement ``node.interfaces.ISequenceNode``. In the context\nof this library, a sequence is an implementation of the methods\nspecified in the ``MutableSequence`` of pythons abstract base classes respective\n``zope.interface.common.collections.IMutableSequence``.\n\nUsing a list node:\n\n.. code-block:: python\n\n    from node.base import BaseNode\n    from node.base import ListNode\n\n    root = ListNode(name='listroot')\n    root.insert(0, BaseNode())\n    root.insert(1, BaseNode())\n\nCheck tree structure with ``printtree``:\n\n.. code-block:: pycon\n\n    >>> root.printtree()\n    <class 'node.base.ListNode'>: listnode\n      <class 'node.base.BaseNode'>: 0\n      <class 'node.base.BaseNode'>: 1\n\n.. note::\n\n    Sequence nodes are introduced as of node 1.0 and are not as feature rich\n    as mapping nodes (yet). If you find inconsistencies or missing features,\n    please file an issue or create a pull request at github.\n\n\nBehaviors\n~~~~~~~~~\n\n``node`` utilizes the `plumber <http://pypi.python.org/pypi/plumber>`_ package.\n\nThe different functionalities of nodes are provided as plumbing behaviors:\n\n.. code-block:: python\n\n    from node.behaviors import DefaultInit\n    from node.behaviors import MappingNode\n    from node.behaviors import OdictStorage\n    from plumber import plumbing\n\n    @plumbing(\n        DefaultInit,\n        MappingNode,\n        OdictStorage)\n    class CustomNode:\n        pass\n\nWhen inspecting the ``CustomNode`` class, we can see it was plumbed using given\nbehaviors, now representing a complete node implementation:\n\n.. code-block:: pycon\n\n    >>> dir(CustomNode)\n    ['__bool__', '__class__', '__contains__', '__delattr__', '__delitem__',\n    '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',\n    '__getattribute__', '__getitem__', '__gt__', '__hash__', '__implemented__',\n    '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__',\n    '__module__', '__name__', '__ne__', '__new__', '__nonzero__', '__parent__',\n    '__plumbing__', '__plumbing_stacks__', '__provides__', '__reduce__',\n    '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__',\n    '__str__', '__subclasshook__', '__weakref__', 'acquire', 'clear', 'copy',\n    'deepcopy', 'detach', 'filtereditems', 'filtereditervalues', 'filteredvalues',\n    'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys',\n    'name', 'noderepr', 'parent', 'path', 'pop', 'popitem', 'printtree', 'root',\n    'setdefault', 'storage', 'treerepr', 'update', 'values']\n\nPlease read the documentation of ``plumber`` for detailed information about the\nplumbing system.\n\n\nAttributes\n~~~~~~~~~~\n\nWhile it is not strictly necessary, it's a good idea to separate the\nhierarchical structure of a model from the node related attributes to avoid\nnaming conflicts. Attributes are provided via ``node.behaviors.Attributes``\nplumbing behavior:\n\n.. code-block:: python\n\n    from node.behaviors import Attributes\n    from node.behaviors import DefaultInit\n    from node.behaviors import DictStorage\n    from node.behaviors import MappingNode\n    from plumber import plumbing\n\n    @plumbing(\n        Attributes,\n        DefaultInit,\n        MappingNode,\n        DictStorage)\n    class NodeWithAttributes:\n        pass\n\nThe node now provides an ``attrs`` attribute. Node attributes are itself just\na node:\n\n.. code-block:: pycon\n\n    >>> node = NodeWithAttributes()\n    >>> attrs = node.attrs\n    >>> attrs\n    <NodeAttributes object 'None' at ...>\n\n    >>> attrs['foo'] = 'foo'\n\nIf it's desired to access attribute members via python attribute access,\n``attribute_access_for_attrs`` must be set on node:\n\n.. code-block:: pycon\n\n    >>> node.attribute_access_for_attrs = True\n    >>> attrs = node.attrs\n    >>> attrs.foo = 'bar'\n    >>> attrs.foo\n    'bar'\n\nA custom attributes implementation can be set by defining\n``attributes_factory`` on the node:\n\n.. code-block:: python\n\n    from node.behaviors import NodeAttributes\n\n    class CustomAttributes(NodeAttributes):\n        pass\n\n    class CustomAttributesNode(NodeWithAttributes):\n        attributes_factory = CustomAttributes\n\nThis factory is then used to instantiate the attributes:\n\n.. code-block:: pycon\n\n    >>> node = CustomAttributesNode()\n    >>> node.attrs\n    <CustomAttributes object 'None' at ...>\n\n\nSchema\n~~~~~~\n\nTo describe the data types of node members, this package provides a mechanism\nfor defining schemata.\n\nThis can happen in different ways. One is to define the schema for node members\ndirectly. This is useful for nodes representing a leaf in the hierarchy or for\nnode attribute nodes:\n\n.. code-block:: python\n\n    from node import schema\n    from node.base import BaseNode\n    from node.behaviors import DefaultInit\n    from node.behaviors import DictStorage\n    from node.behaviors import MappingNode\n    from node.behaviors import Schema\n    from plumber import plumbing\n\n    @plumbing(\n        DefaultInit,\n        MappingNode,\n        DictStorage,\n        Schema)\n    class SchemaNode:\n        schema = {\n            'int': schema.Int(),\n            'float': schema.Float(default=1.),\n            'str': schema.Str(),\n            'bool': schema.Bool(default=False),\n            'node': schema.Node(BaseNode)\n        }\n\nChildren defined in the schema provide a default value. If not explicitely\ndefined, the default value is always ``node.utils.UNSET``:\n\n.. code-block:: pycon\n\n    >>> node = SchemaNode()\n    >>> node['int']\n    <UNSET>\n\n    >>> node['float']\n    1.0\n\n    >>> node['bool']\n    False\n\nChildren defined in the schema are validated against the defined type when\nsetting it's value:\n\n.. code-block:: pycon\n\n    >>> node = SchemaNode()\n    >>> node['int'] = 'A'\n    Traceback (most recent call last):\n      ...\n    ValueError: A is no <class 'int'> type\n\nFor accessing members defined in the schema as node attributes,\n``SchemaAsAttributes`` plumbing behavior can be used:\n\n.. code-block:: python\n\n    from node.behaviors import SchemaAsAttributes\n\n    @plumbing(SchemaAsAttributes)\n    class SchemaAsAttributesNode(BaseNode):\n        schema = {\n            'int': schema.Int(default=1),\n        }\n\nNode ``attrs`` now provides access to the schema members:\n\n.. code-block:: pycon\n\n    >>> node = SchemaAsAttributesNode()\n    >>> node.attrs['int']\n    1\n\nSchema members can also be defined as class attributes. This is syntactically\nthe most elegant way, but comes with the tradeoff of possible naming conflicts:\n\n.. code-block:: python\n\n    from node.behaviors import SchemaProperties\n\n    @plumbing(\n        DefaultInit,\n        MappingNode,\n        DictStorage,\n        SchemaProperties)\n    class SchemaPropertiesNode:\n        text = schema.Str(default='Text')\n\nHere we access ``text`` as class attribute:\n\n.. code-block:: pycon\n\n    >>> node = SchemaPropertiesNode()\n    >>> node.text\n    'Text'\n\n    >>> node.text = 1\n    Traceback (most recent call last):\n      ...\n    ValueError: 1 is no <class 'str'> type\n\n\nPlumbing Behaviors\n------------------\n\nGeneral Behaviors\n~~~~~~~~~~~~~~~~~\n\n**node.behaviors.DefaultInit**\n    Plumbing behavior providing default ``__init__`` function on node. This\n    behavior is going to be deprecated in future versions. Use\n    ``node.behaviors.NodeInit`` instead.\n    See ``node.interfaces.IDefaultInit``.\n\n**node.behaviors.NodeInit**\n    Plumbing behavior for transparent setting of ``__name__`` and ``__parent__``\n    at object initialization time.\n    See ``node.interfaces.INodeInit``.\n\n**node.behaviors.Node**\n    Fill in gaps for full INode API. See ``node.interfaces.INode``.\n\n**node.behaviors.ContentishNode**\n    A node which can contain children. See\n    ``node.interfaces.IContentishNode``. Concrete implementations are\n    ``node.behaviors.MappingNode`` and ``node.behaviors.SequenceNode``.\n\n**node.behaviors.Attributes**\n    Provide attributes on node. See ``node.interfaces.IAttributes``. If\n    ``node.behaviors.Nodespaces`` is applied on node, the attributes instance\n    gets stored internally in ``__attrs__`` nodespace, otherwise its set on\n    ``__attrs__`` attribute.\n\n**node.behaviors.Events**\n    Provide an event registration and dispatching mechanism.\n    See ``node.interfaces.IEvents``.\n\n**node.behaviors.BoundContext**\n    Mechanism for scoping objects to interfaces and classes.\n    See ``node.interfaces.IBoundContext``.\n\n**node.behaviors.NodeReference**\n    Plumbing behavior holding an index of nodes contained in the tree.\n    See ``node.interfaces.INodeReference``.\n\n**node.behaviors.WildcardFactory**\n    Plumbing behavior providing factories by wildcard patterns.\n    See ``node.interfaces.IWildcardFactory``.\n\n\nMapping Behaviors\n~~~~~~~~~~~~~~~~~\n\n**node.behaviors.MappingNode**\n    Turn an object into a mapping node. Extends ``node.behaviors.Node``.\n    See ``node.interfaces.IMappingNode``.\n\n**node.behaviors.MappingAdopt**\n    Plumbing behavior that provides ``__name__`` and ``__parent__`` attribute\n    adoption on child nodes of mapping.\n    See ``node.interfaces.IMappingAdopt``.\n\n**node.behaviors.MappingConstraints**\n    Plumbing behavior for constraints on mapping nodes.\n    See ``node.interfaces.IMappingConstraints``.\n\n**node.behaviors.UnicodeAware**\n    Plumbing behavior to ensure unicode for keys and string values.\n    See ``node.interfaces.IUnicodeAware``.\n\n**node.behaviors.Alias**\n    Plumbing behavior that provides aliasing of child keys.\n    See ``node.interfaces.IAlias``.\n\n**node.behaviors.AsAttrAccess**\n    Plumbing behavior to get node as IAttributeAccess implementation.\n    See ``node.interfaces.IAsAttrAccess``.\n\n**node.behaviors.ChildFactory**\n    Plumbing behavior providing child factories.\n    See ``node.interfaces.IChildFactory``.\n\n**node.behaviors.FixedChildren**\n    Plumbing Behavior that initializes a fixed dictionary as children.\n    See ``node.interfaces.IFixedChildren``.\n\n**node.behaviors.Nodespaces**\n    Plumbing behavior for providing nodespaces on node.\n    See ``node.interfaces.INodespaces``.\n\n**node.behaviors.Lifecycle**\n    Plumbing behavior taking care of lifecycle events.\n    See ``node.interfaces.ILifecycle``.\n\n**node.behaviors.AttributesLifecycle**\n    Plumbing behavior for handling lifecycle events on attribute manipulation.\n    See ``node.interfaces.IAttributesLifecycle``.\n\n**node.behaviors.Invalidate**\n    Plumbing behavior for node invalidation.\n    See ``node.interfaces.Invalidate``.\n\n**node.behaviors.VolatileStorageInvalidate**\n    Plumbing behavior for invalidating nodes using a volatile storage.\n    See ``node.interfaces.Invalidate``.\n\n**node.behaviors.Cache**\n    Plumbing behavior for caching.\n    See ``node.interfaces.ICache``.\n\n**node.behaviors.MappingOrder**\n    Plumbing behavior for ordering support on mapping nodes.\n    See ``node.interfaces.IMappingOrder``.\n\n**node.behaviors.UUIDAware**\n    Plumbing behavior providing a uuid on nodes.\n    See ``node.interfaces.IUUIDAware``.\n\n**node.behaviors.MappingReference**\n    Plumbing behavior to provide ``node.interfaces.INodeReference`` on mapping\n    nodes. See ``node.interfaces.IMappingReference``.\n\n**node.behaviors.MappingStorage**\n    Provide abstract mapping storage access.\n    See ``node.interfaces.IMappingStorage``.\n\n**node.behaviors.DictStorage**\n    Provide dictionary storage. Extends ``node.behaviors.MappingStorage``.\n    See ``node.interfaces.IMappingStorage``.\n\n**node.behaviors.OdictStorage**\n    Provide ordered dictionary storage. Extends\n    ``node.behaviors.MappingStorage``. See ``node.interfaces.IMappingStorage``.\n\n**node.behaviors.Fallback**\n    Provide a way to fall back to values by subpath stored on another node.\n    See ``node.interfaces.IFallback``.\n\n**node.behaviors.Schema**\n    Provide schema validation and value serialization on node values.\n    See ``node.interfaces.ISchema``.\n\n**node.behaviors.SchemaAsAttributes**\n    Provide schema validation and value serialization on node values via\n    dedicated attributes object.\n    See ``node.interfaces.ISchemaAsAttributes``.\n\n**node.behaviors.SchemaProperties**\n    Provide schema fields as class properties.\n    See ``node.interfaces.ISchemaProperties``.\n\n**node.behaviors.MappingFilter**\n    Filter mapping children by class or interface.\n    See ``node.interfaces.IChildFilter``.\n\n\nSequence Behaviors\n~~~~~~~~~~~~~~~~~~\n\n**node.behaviors.SequenceNode**\n    Turn an object into a sequence node. Extends ``node.behaviors.Node``.\n    See ``node.interfaces.IMappingNode``.\n\n**node.behaviors.SequenceAdopt**\n    Plumbing behavior that provides ``__name__`` and ``__parent__`` attribute\n    adoption on child nodes of sequence.\n    See ``node.interfaces.ISequenceAdopt``.\n\n**node.behaviors.SequenceConstraints**\n    Plumbing behavior for constraints on sequence nodes.\n    See ``node.interfaces.ISequenceConstraints``.\n\n**node.behaviors.SequenceStorage**\n    Provide abstract sequence storage access.\n    See ``node.interfaces.ISequenceStorage``.\n\n**node.behaviors.ListStorage**\n    Provide list storage. See ``node.interfaces.ISequenceStorage``.\n\n**node.behaviors.SequenceReference**\n    Plumbing behavior to provide ``node.interfaces.INodeReference`` on sequence\n    nodes. See ``node.interfaces.ISequenceReference``.\n\n**node.behaviors.SequenceFilter**\n    Filter sequence children by class or interface.\n    See ``node.interfaces.IChildFilter``.\n\n**node.behaviors.SequenceOrder**\n    Plumbing behavior for ordering support on sequence nodes.\n    See ``node.interfaces.ISequenceOrder``.\n\n\nJSON Serialization\n------------------\n\nNodes can be serialized to and deserialized from JSON:\n\n.. code-block:: pycon\n\n    >>> from node.serializer import serialize\n    >>> json_dump = serialize(BaseNode(name='node'))\n\n    >>> from node.serializer import deserialize\n    >>> deserialize(json_dump)\n    <BaseNode object 'node' at ...>\n\nFor details on serialization API please read file in\n``docs/archive/serializer.rst``.\n\n\nPython Versions\n---------------\n\n- Python 2.7, 3.7+\n- May work with other versions (untested)\n\n\nContributors\n============\n\n- Robert Niederreiter\n- Florian Friesdorf\n- Jens Klein\n\n\n\nChanges\n=======\n\n1.2.1 (2023-04-16)\n------------------\n\n- Replace deprecated import of ``Order`` with ``MappingOrder`` in ``node.base``.\n  [rnix]\n\n\n1.2 (2022-12-05)\n----------------\n\n- Do not overwrite ``uuid`` in ``node.behaviors.UUIDAware.__init__`` if\n  ``uuid`` already set.\n  [rnix]\n\n- Rename ``node.interfaces.IOrder`` to ``node.interfaces.IMappingOrder``\n  and ``node.behaviors.Order`` to ``node.behaviors.MappingOrder``.\n  B/C is kept.\n  [rnix]\n\n- Introduce ``node.behaviors.ISequenceOrder`` and\n  ``node.interfaces.SequenceOrder``.\n  [rnix]\n\n- Introduce ``node.interfaces.INodeOrder``. Used as base for\n  ``node.interfaces.IMappingOrder`` and ``node.interfaces.ISequenceOrder``.\n  [rnix]\n\n- Add rich comparison functions ``__lt__``, ``__le__``, ``__gt__`` and\n  ``__ge__`` to ``node.utils.Unset``.\n  [rnix]\n\n**Breaking changes**:\n\n- Importing B/C ``Order`` behavior from ``node.behaviors.order``\n  not works any more. Please import from ``node.behaviors``.\n  [rnix]\n\n\n1.1 (2022-10-06)\n----------------\n\n- Add ``node.schema.DateTime``, ``node.schema.DateTimeSerializer`` and\n  ``node.schema.datetime_serializer``.\n  [rnix]\n\n- Subclass ``threading.local`` for\n  ``node.behaviors.lifecycle._lifecycle_context``,\n  ``node.behaviors.events._attribute_subscribers`` and\n  ``node.behaviors.schema._schema_property`` objects in order to safely provide\n  default values.\n  [rnix]\n\n- Introduce ``node.interfaces.IChildFilter``, ``node.behaviors.MappingFilter``\n  and ``node.behaviors.SequenceFilter``.\n  [rnix]\n\n- Introduce ``node.interfaces.IWildcardFactory`` and\n  ``node.behaviors.WildcardFactory``.\n  [rnix]\n\n- Introduce ``node.interfaces.INodeInit`` and ``node.behaviors.NodeInit``.\n  [rnix]\n\n- Deprecate ``IFixedChildren.fixed_children_factories`` Use\n  ``IFixedChildren.factories`` instead.\n  [rnix]\n\n- Introduce ``node.interfaces.IContentishNode`` and\n  ``node.behaviors.ContentishNode``. Use as base for mapping and sequence nodes.\n  [rnix]\n\n- ``insertbefore``, ``insertafter`` and ``swap`` in ``node.behaviors.Order``\n  alternatively accept node names as arguments where possible.\n  [rnix]\n\n- ``insertbefore``, ``insertafter``, and ``insertfirst`` and ``insertlast`` in\n  ``node.behaviors.Order`` internally use ``movebefore``, ``moveafter``,\n  ``movefirst`` and ``movelast`` of ``odict`` to avoid modifying the data\n  structure before ``__setitem__`` gets called.\n  [rnix]\n\n- Extend ``node.interfaces.IOrder``  respective ``node.behaviors.Order``\n  by ``movebefore``, ``moveafter``, ``movefirst`` and ``movelast``.\n  [rnix]\n\n- Reset ``__parent__`` in ``node.behaviors.Node.detach``. Node is no longer\n  contained in tree.\n  [rnix]\n\n- Introduce ``IndexViolationError`` which inherits from ``ValueError`` and\n  raise it in reference related behaviors instead of ``ValueError`` where\n  appropriate.\n  [rnix]\n\n- Introduce ``node.interfaces.INodeReference`` and\n  ``node.behaviors.NodeReference``.\n  [rnix]\n\n- Introduce ``node.interfaces.ISequenceReference`` and\n  ``node.behaviors.SequenceReference``.\n  [rnix]\n\n- Rename ``node.interfaces.IReference`` to ``node.interfaces.IMappingReference``\n  and ``node.behaviors.Reference`` to ``node.behaviors.MappingReference``.\n  B/C is kept.\n  [rnix]\n\n**Breaking changes**:\n\n- Remove ``_notify_suppress`` flag from ``Lifecycle`` behavior. Introduce\n  ``suppress_lifecycle_events`` contextmanager as substitute.\n  [rnix]\n\n- Importing ``ChildFactory`` and ``FixedChildren`` from\n  ``node.behaviors.common`` not works any more. Please import from\n  ``node.behaviors``.\n  [rnix]\n\n- Importing B/C ``Reference`` behavior from ``node.behaviors.reference``\n  not works any more. Please import from ``node.behaviors``.\n  [rnix]\n\n\n1.0 (2022-03-17)\n----------------\n\n- Implement ``__copy__`` and ``__deepcopy__`` on ``node.utils.UNSET``.\n  [rnix]\n\n- Introduce ``node.interfaces.ISequenceConstraints`` and\n  ``node.behaviors.SequenceConstraints``.\n  [rnix]\n\n- Rename ``node.interfaces.INodeChildValidate`` to\n  ``node.interfaces.IMappingConstraints`` and\n  ``node.behaviors.NodeChildValidate`` to ``node.behaviors.MappingConstraints``.\n  ``MappingConstraints`` implementation moved from ``node.behaviors.common`` to\n  ``node.behaviors.constraints``. B/C is kept.\n  [rnix]\n\n- Introduce ``node.interfaces.ISequenceAdopt`` and\n  ``node.behaviors.SequenceAdopt``.\n  [rnix]\n\n- ``MappingAdopt`` now catches all exceptions instead of only\n  ``AttributeError``, ``KeyError`` and ``ValueError``.\n  [rnix]\n\n- Rename ``node.interfaces.IAdopt`` to ``node.interfaces.IMappingAdopt`` and\n  ``node.behaviors.Adopt`` to ``node.behaviors.MappingAdopt``. ``MappingAdopt``\n  implementation moved from ``node.behaviors.common`` to\n  ``node.behaviors.adopt``. B/C is kept.\n  [rnix]\n\n- ``node.behaviors.Attributes`` now also works if\n  ``node.behaviors.Nodespaces`` is not applied.\n  [rnix]\n\n- Introduce ``node.behaviors.Node`` which implements only\n  ``node.interfaces.INode`` contract. It is used as base for\n  ``node.behaviors.MappingNode`` and ``node.behaviors.SequcneNode``.\n  [rnix]\n\n- Do not inherit ``node.interfaces.INode`` from\n  ``zope.interfaces.common.mapping.IFullMapping`` any more. Data model specific\n  interfaces are added now via ``node.interfaces.IMappingNode`` and\n  ``node.interfaces.ISequenceNode``.\n  [rnix]\n\n- Introduce sequence nodes. Sequence nodes are implemented via\n  ``node.behaviors.SequcneNode`` and ``node.behaviors.ListStorage``.\n  [rnix]\n\n- Rename ``node.interfaces.INodify`` to ``node.interfaces.IMappingNode`` and\n  ``node.behaviors.Nodify`` to ``node.behaviors.MappingNode``. ``MappingNode``\n  implementation moved from ``node.behaviors.nodify`` to\n  ``node.behaviors.mapping``. B/C is kept.\n  [rnix]\n\n- Rename ``node.interfaces.IStorage`` to ``node.interfaces.IMappingStorage``\n  and ``node.behaviors.Storage`` to ``node.behaviors.Storage``. B/C is kept.\n  [rnix]\n\n- Add key and value type validation to schema fields where appropriate.\n  [rnix]\n\n- Introduce serializer support to schema fields. Add a couple of concrete field\n  serializer implementations to ``node.schema.serializer``.\n  [rnix]\n\n- Add ``ODict`` and ``Node`` schema fields to ``node.schema.fields``.\n  [rnix]\n\n- Add ``node.schema.fields.IterableField`` and use as base class for\n  ``List``, ``Tuple`` and ``Set`` schema fields.\n\n- Introduce ``node.behaviors.schema.SchemaProperties`` plumbing behavior.\n  [rnix]\n\n- Split up ``node.schema`` module into a package.\n  [rnix]\n\n- Introduce ``node.behaviors.context.BoundContext`` plumbing behavior.\n  [rnix]\n\n**Breaking changes**:\n\n- Remove ``node.behaviors.GetattrChildren``. See ``node.utils.AttributeAccess``\n  instead if you need to access node children via ``__getattr__``.\n  [rnix]\n\n- Importing B/C ``Adopt`` behavior from ``node.behaviors.common``\n  not works any more. Please import from ``node.behaviors``.\n  [rnix]\n\n- Importing B/C ``NodeChildValidate`` behavior from ``node.behaviors.common``\n  not works any more. Please import from ``node.behaviors``.\n  [rnix]\n\n- Importing B/C ``Nodify`` behavior from ``node.behaviors.nodify``\n  not works any more. Please import from ``node.behaviors``.\n  [rnix]\n\n- Remove deprecated B/C import location ``node.parts``.\n  [rnix]\n\n- ``node.behaviors.schema.Schema`` no longer considers wildcard fields.\n  [rnix]\n\n- ``node.behaviors.schema.Schema.__setitem__`` deletes value from related\n  storage for field if value is ``node.utils.UNSET``.\n  [rnix]\n\n- ``node.behaviors.schema.Schema.__getitem__`` always returns default value for\n  field instead of raising ``KeyError`` if no default is set.\n  [rnix]\n\n- Default value of ``node.schema.fields.Field.default`` is ``node.utils.UNSET``\n  now.\n  [rnix]\n\n- ``node.schema.fields.Field.validate`` raises exception if validation fails\n  instead of returning boolean.\n  [rnix]\n\n\n0.9.28 (2021-11-08)\n-------------------\n\n- Add missing ``node.interfaces.INodeAttributes`` interface.\n  [rnix]\n\n- Add missing ``attribute_access_for_attrs`` attribute to ``IAttributes``\n  interface.\n  [rnix]\n\n- Rename ``node.behaviors.common.NodeChildValidate.allow_non_node_childs``\n  to ``allow_non_node_children``. A Deprecation warning is printed if the\n  old attribute is used.\n  [rnix]\n\n- Introduce ``node.behaviors.schema.Schema``,\n  ``node.behaviors.schema.SchemaAsAttributes`` and related schema definitions\n  in ``node.schema``.\n  [rnix]\n\n\n0.9.27 (2021-10-21)\n-------------------\n\n- Expose ``first_key``, ``last_key``, ``next_key`` and ``prev_key`` from\n  odict storage on ``Order`` behavior.\n  [rnix, 2021-10-21]\n\n- Add basic serializer settings mechanism.\n  [rnix, 2021-07-20]\n\n\n0.9.26 (2021-05-10)\n-------------------\n\n- Use ``node.utils.safe_decode`` in ``node.behaviors.nodify.Nodify.treerepr``.\n  [rnix, 2021-05-04]\n\n- Add ``node.utils.safe_encode`` and ``node.utils.safe_decode``.\n  [rnix, 2021-05-04]\n\n\n0.9.25 (2020-03-30)\n-------------------\n\n- Introduce ``uuid_factory`` function on ``node.interfaces.IUUIDAware`` and\n  implement default function in ``node.behaviors.common.UUIDAware``.\n  [rnix, 2020-03-01]\n\n- Rename ``NodeTestCase.expect_error`` to ``NodeTestCase.expectError``.\n  [rnix, 2019-09-04]\n\n- Rename ``NodeTestCase.check_output`` to ``NodeTestCase.checkOutput``.\n  [rnix, 2019-09-04]\n\n- Introduce ``prefix`` keyword argument in ``Nodify.treerepr``.\n  [rnix, 2019-09-04]\n\n\n0.9.24 (2019-07-10)\n-------------------\n\n- Overhaul ``node.behaviors.Order``. Use related functions from ``odict`` where\n  appropriate.\n  [rnix, 2019-07-10]\n\n- Remove superfluous ``extra_require`` from ``setup.py``.\n  [rnix, 2019-04-25]\n\n- Drop Support for python < 2.7 and < 3.3.\n  [rnix, 2019-04-25]\n\n\n0.9.23 (2018-11-07)\n-------------------\n\n- Use property decorators for ``node.behaviors.reference.Reference.uuid``.\n  [rnix, 2017-12-15]\n\n\n0.9.22 (2017-07-18)\n-------------------\n\n- Add ``always_dispatch`` keyword argument to\n  ``node.behaviors.events.EventAttribute`` constructor which defines whether\n  events are always dispatched on ``__set__``, not only if attribute value\n  changes.\n  [rnix, 2017-06-20]\n\n- Use ``node.utils.UNSET`` as default ``default`` value in\n  ``node.behaviors.events.EventAttribute.__init__``.\n  [rnix, 2017-06-19]\n\n- Introduce ``node.behaviors.events.EventAttribute.subscriber`` decorator which\n  can be used to register attribute subscribers.\n  [rnix, 2017-06-19]\n\n- Move event dispatching related classes and functions from ``node.events``\n  to ``node.behaviors.events`` and import it from there in ``node.events``.\n  [rnix, 2017-06-16]\n\n- Introduce ``node.interfaces.IEvents`` and implement\n  ``node.behaviors.events.Events`` behavior. Contains business logic from\n  ``node.events.EventDispatcher``. Use new behavior on ``EventDispatcher``.\n  [rnix, 2017-06-16]\n\n- Create ``suppress_events`` context manager which can be used to\n  suppress event notification in conjunction with ``node.behaviors.Events``\n  behavior.\n  [rnix, 2017-06-15]\n\n- Create ``node.behaviors.fallback.fallback_processing`` context manager and\n  and use it in ``node.behaviors.fallback.Fallback.__getitem__`` to check\n  whether fallback processing is active.\n  [rnix, 2017-06-15]\n\n\n0.9.21 (2017-06-15)\n-------------------\n\n- Introduce ``node.events.EventDispatcher`` and ``node.events.EventAttribute``.\n  [rnix, 2017-06-15]\n\n- Use ``setattr`` in ``instance_property`` decorator instead of\n  ``object.__setattr__`` in order to avoid errors with custom low level\n  ``__setattr__`` implementations.\n  [rnix, 2017-06-14]\n\n\n0.9.20 (2017-06-07)\n-------------------\n\n- Type cast sort key to ``node.compat.UNICODE_TYPE`` in\n  ``node.behaviors.Nodify.treerepr`` to avoid unicode decode errors.\n  [rnix, 2017-06-07]\n\n\n0.9.19 (2017-06-07)\n-------------------\n\n- Python 3 and pypy compatibility.\n  [rnix, 2017-06-02]\n\n- Drop support for Python < 2.7.\n  [rnix, 2017-06-02]\n\n- Add ``__bool__`` to ``node.behaviors.Nodify``.\n  [rnix, 2017-06-02]\n\n- Add ``__bool__`` to ``node.utils.UNSET``.\n  [rnix, 2017-06-02]\n\n- Add ``treerepr`` in ``node.behaviors.nodify.Nodify`` and move code from\n  ``printtree`` to it. Returs tree representation as string instead of printing\n  it. ``printtree`` uses ``treerepr`` now. As enhancement ``treerepr`` sorts\n  children of node if it does not implement ``IOrdered`` in order to ensure\n  consistend output which can be used to write tests against.\n  [rnix, 2017-06-02]\n\n- Use ``object.__getattribute__`` explicitely in\n  ``node.utils.instance_property`` to check whether property value already has\n  been computed in order to avoid problems when oberwriting ``__getattr__``\n  on classes using ``instance_property`` decorator.\n  [rnix, 2017-06-02]\n\n\n0.9.18.1 (2017-02-23)\n---------------------\n\n- Fix permissions.\n  [rnix, 2017-02-23]\n\n\n0.9.18 (2017-02-14)\n-------------------\n\n- Add ``node.utils.node_by_path``.\n  [rnix, 2017-02-07]\n\n- Do not depend on ``unittest2`` since its is not used.\n  [jensens, 2017-01-17]\n\n- Add ``node.behaviors.Fallback`` behavior.\n  [jensens, 2017-01-17]\n\n\n0.9.17 (2017-01-17)\n-------------------\n\n- Add basic JSON serializer and deserializer.\n  [rnix, 2016-12-03]\n\n\n0.9.16 (2015-10-08)\n-------------------\n\n- Only encode name in ``node.behaviors.nodify.Nodify.__repr__`` and\n  ``node.behaviors.nodify.Nodify.noderepr`` if name is unicode instance.\n  [rnix, 2015-10-03]\n\n- Improve ``node.behaviors.nodify.Nodify.printtree``. None node children are\n  printed with key.\n  [rnix, 2015-10-03]\n\n\n0.9.15 (2014-12-17)\n-------------------\n\n- Fix dependency declaration to ``odict`` in order to make setuptools 8.x+\n  happy; using ``>=`` instead of ``>`` now.\n  [jensens, 2014-12-17]\n\n\n0.9.14\n------\n\n- use ``plumbing`` decorator instead of ``plumber`` metaclass.\n  [rnix, 2014-07-31]\n\n\n0.9.13\n------\n\n- Introduce ``node.behaviors.cache.VolatileStorageInvalidate``.\n  [rnix, 2014-01-15]\n\n\n0.9.12\n------\n\n- Add ``zope.component`` to install dependencies.\n  [rnix, 2013-12-09]\n\n\n0.9.11\n------\n\n- Use ``node.utils.UNSET`` instance in\n  ``node.behaviors.mapping.ExtendedWriteMapping.pop``.\n  [rnix, 2013-02-10]\n\n- Improve ``node.utils.Unset``. Add ``Unset`` instance at\n  ``node.utils.UNSET``.\n  [rnix, 2013-02-10]\n\n\n0.9.10\n------\n\n- Fix ``node.utils.StrCodec.encode`` to return value as is if str and decoding\n  failed.\n  [rnix, 2012-11-07]\n\n\n0.9.9\n-----\n\n- Python 2.7 compatibility.\n  [rnix, 2012-10-15]\n\n- Remove ``zope.component.event`` B/C.\n  [rnix, 2012-10-15]\n\n- Remove ``zope.location`` B/C.\n  [rnix, 2012-10-15]\n\n- Remove ``zope.lifecycleevent`` B/C.\n  [rnix, 2012-10-15]\n\n- Pep8.\n  [rnix, 2012-10-15]\n\n\n0.9.8\n-----\n\n- Deprecate the use of ``node.parts``. Use ``node.behaviors`` instead.\n  [rnix, 2012-07-28]\n\n- Adopt to ``plumber`` 1.2\n  [rnix, 2012-07-28]\n\n\n0.9.7\n-----\n\n- Introduce ``node.interfaces.IOrdered`` Marker interface. Set this interface\n  on ``node.parts.storage.OdictStorage``.\n  [rnix, 2012-05-21]\n\n- ``node.parts.mapping.ClonableMapping`` now supports ``deepcopy``.\n  [rnix, 2012-05-18]\n\n- Use ``zope.interface.implementer`` instead of ``zope.interface.implements``\n  all over the place.\n  [rnix, 2012-05-18]\n\n- Remove superfluos interfaces.\n  [rnix, 2012-05-18]\n\n- Remove ``Zodict`` from ``node.utils``.\n  [rnix, 2012-05-18]\n\n- Remove ``AliasedNodespace``, use ``Alias`` part instead.\n  [rnix, 2012-05-18]\n\n- Move aliaser objects from ``node.aliasing`` to ``node.parts.alias``.\n  [rnix, 2012-05-18]\n\n- Remove ``composition`` module.\n  [rnix, 2012-05-18]\n\n- Remove ``bbb`` module.\n  [rnix, 2012-05-18]\n\n\n0.9.6\n-----\n\n- Do not inherit ``node.parts.Reference`` from ``node.parts.UUIDAware``.\n  [rnix, 2012-01-30]\n\n- Set ``uuid`` in ``node.parts.Reference.__init__`` plumb.\n  [rnix, 2012-01-30]\n\n\n0.9.5\n-----\n\n- add ``node.parts.nodify.Nodify.acquire`` function.\n  [rnix, 2011-12-05]\n\n- add ``node.parts.ChildFactory`` plumbing part.\n  [rnix, 2011-12-04]\n\n- add ``node.parts.UUIDAware`` plumbing part.\n  [rnix, 2011-12-02]\n\n- fix ``node.parts.Order.swap`` in order to work with pickled nodes.\n  [rnix, 2011-11-28]\n\n- use ``node.name`` instead of ``node.__name__`` in\n  ``node.parts.nodify.Nodify.path``.\n  [rnix, 2011-11-17]\n\n- add ``swap`` to  ``node.parts.Order``.\n  [rnix, 2011-10-05]\n\n- add ``insertfirst`` and ``insertlast`` to ``node.parts.Order``.\n  [rnix, 2011-10-02]\n\n\n0.9.4\n-----\n\n- add ``node.utils.debug`` decorator.\n  [rnix, 2011-07-23]\n\n- remove non storage contract specific properties from\n  ``node.aliasing.AliasedNodespace``\n  [rnix, 2011-07-18]\n\n- ``node.aliasing`` test completion\n  [rnix, 2011-07-18]\n\n- Add non strict functionality to ``node.aliasing.DictAliaser`` for accessing\n  non aliased keys as is as fallback\n  [rnix, 2011-07-18]\n\n- Consider ``INode`` implementing objects in ``node.utils.StrCodec``\n  [rnix, 2011-07-16]\n\n- Remove duplicate implements in storage parts\n  [rnix, 2011-05-16]\n\n\n0.9.3\n-----\n\n- Increase test coverage\n  [rnix, 2011-05-09]\n\n- Add interfaces ``IFixedChildren`` and ``IGetattrChildren`` for related parts.\n  [rnix, 2011-05-09]\n\n- Rename ``Unicode`` part to ``UnicodeAware``.\n  [rnix, 2011-05-09]\n\n- Add ``node.utils.StrCodec``.\n  [rnix, 2011-05-09]\n\n- Inherit ``INodify`` interface from ``INode``.\n  [rnix, 2011-05-08]\n\n- Locking tests. Add ``time.sleep`` after thread start.\n  [rnix, 2011-05-08]\n\n- Cleanup ``BaseTester``, remove ``sorted_output`` flag (always sort), also\n  search class bases for detection in ``wherefrom``.\n  [rnix, 2011-05-08]\n\n- Remove useless try/except in ``utils.AttributeAccess``.\n  [rnix, 2011-05-08]\n\n- Add ``instance_property`` decorator to utils.\n  [rnix, 2011-05-06]\n\n- Add ``FixedChildren`` and ``GetattrChildren`` parts.\n  [chaoflow, 2011-04-22]\n\n\n0.9.2\n-----\n\n- Add ``__nonzero__`` on ``Nodifiy`` part always return True.\n  [rnix, 2011-03-15]\n\n\n0.9.1\n-----\n\n- Provide ``node.base.Node`` with same behavior like ``zodict.Node`` for\n  migration purposes.\n  [rnix, 2011-02-08]\n\n\n0.9\n---\n\n- Make it work [rnix, chaoflow, et al]\n\n\nLicense\n=======\n\nCopyright (c) 2009-2021, BlueDynamics Alliance, Austria\nCopyright (c) 2021-2022, Node Contributors\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice, this\n  list of conditions and the following disclaimer in the documentation and/or\n  other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n",
    "bugtrack_url": null,
    "license": "Simplified BSD",
    "summary": "Building data structures as node trees",
    "version": "1.2.1",
    "split_keywords": [
        "node",
        "tree",
        "fullmapping",
        "dict"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6d14a37915ebc1aaa9e5b3e45dbebe0acc42e64a830e74ac857b3655bee3b96f",
                "md5": "d658435415303a0f64a6a7965490e3ef",
                "sha256": "a25ffafc7bd9f3a4ebe09a41690c1ff42bcf6a23e8a4ad2654be455bf122ebfa"
            },
            "downloads": -1,
            "filename": "node-1.2.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d658435415303a0f64a6a7965490e3ef",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 102666,
            "upload_time": "2023-04-16T06:08:05",
            "upload_time_iso_8601": "2023-04-16T06:08:05.380311Z",
            "url": "https://files.pythonhosted.org/packages/6d/14/a37915ebc1aaa9e5b3e45dbebe0acc42e64a830e74ac857b3655bee3b96f/node-1.2.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "eb63d2c9820b2dbf098c9d410162aa99347f6e06ad7813ded994f18993f67def",
                "md5": "52ca6a7ac216ec12a57cf154de745e4a",
                "sha256": "03c8a0f6845c4a164508fcdd02cada8dde393eec42220b27a69d76677f73c46d"
            },
            "downloads": -1,
            "filename": "node-1.2.1.tar.gz",
            "has_sig": false,
            "md5_digest": "52ca6a7ac216ec12a57cf154de745e4a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 100089,
            "upload_time": "2023-04-16T06:08:08",
            "upload_time_iso_8601": "2023-04-16T06:08:08.682890Z",
            "url": "https://files.pythonhosted.org/packages/eb/63/d2c9820b2dbf098c9d410162aa99347f6e06ad7813ded994f18993f67def/node-1.2.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-04-16 06:08:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "conestack",
    "github_project": "node",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "node"
}
        
Elapsed time: 0.05445s