跳转到主要内容

符合zope.interface的有序字典和zope.location感知节点。

项目描述

需求

  • Python2.4+

用法

Zodict

实现对应zope.interface.common.mapping接口的有序字典。

>>> from zope.interface.common.mapping import IFullMapping
>>> from zodict import Zodict
>>> zod = Zodict()
>>> IFullMapping.providedBy(zod)
True

节点

这是一个提供位置的zodict。在zope方式中,位置意味着节点树中的每个项目都知道其父节点及其自己的名称。

>>> from zope.location.interface import ILocation
>>> from zodict import Node
>>> root = Node('root')
>>> ILocation.providedBy(Node)
True

>>> root['child'] = Node()
>>> root['child'].path
['root', 'child']

>>> child = root['child']
>>> child.__name__
'child'

>>> child.__parent__
<Node object 'root' at ...>

filtereditems函数。

>>> from zope.interface import Interface
>>> from zope.interface import alsoProvides
>>> class IMarker(Interface): pass
>>> alsoProvides(root['child']['subchild'], IMarker)
>>> IMarker.providedBy(root['child']['subchild'])
True

>>> for item in root['child'].filtereditems(IMarker):
...     print item.path
['root', 'child', 'subchild']

节点上的UUID相关操作。

>>> uuid = root['child']['subchild'].uuid
>>> uuid
UUID('...')

>>> root.node(uuid).path
['root', 'child', 'subchild']

>>> root.uuid = uuid
Traceback (most recent call last):
  ...
ValueError: Given uuid was already used for another Node

>>> import uuid
>>> newuuid = uuid.uuid4()

>>> root.uuid = newuuid
>>> root['child'].node(newuuid).path
['root']

节点插入(还存在一个insertafter函数)。

>>> root['child1'] = Node()
>>> root['child2'] = Node()

>>> node = Node('child3')
>>> root.insertbefore(node, root['child2'])
>>> root.printtree()
<class 'zodict.node.Node'>: root
  <class 'zodict.node.Node'>: child1
  <class 'zodict.node.Node'>: child3
  <class 'zodict.node.Node'>: child2

移动一个节点。因此,我们首先需要将我们想要移动的节点从树中分离出来。然后,将分离的节点插入到其他位置。通常,您可以将分离的节点或子树插入到完全不同的树中。

>>> len(root._index.keys())
6

>>> node = root.detach('child4')
>>> node
<Node object 'child4' at ...>

>>> len(node._index.keys())
1
>>> len(root._index.keys())
5

>>> len(root.values())
4

>>> root.insertbefore(node, root['child1'])
>>> root.printtree()
<class 'zodict.node.Node'>: root
  <class 'zodict.node.Node'>: child4
  <class 'zodict.node.Node'>: child1
  <class 'zodict.node.Node'>: child3
  <class 'zodict.node.Node'>: child5
  <class 'zodict.node.Node'>: child2

合并两个节点树。

>>> tree1 = Node()
>>> tree1['a'] = Node()
>>> tree1['b'] = Node()
>>> tree2 = Node()
>>> tree2['d'] = Node()
>>> tree2['e'] = Node()
>>> tree1._index is tree2._index
False

>>> len(tree1._index.keys())
3

>>> tree1.printtree()
<class 'zodict.node.Node'>: None
  <class 'zodict.node.Node'>: a
  <class 'zodict.node.Node'>: b

>>> len(tree2._index.keys())
3

>>> tree2.printtree()
<class 'zodict.node.Node'>: None
  <class 'zodict.node.Node'>: d
  <class 'zodict.node.Node'>: e

>>> tree1['c'] = tree2
>>> len(tree1._index.keys())
6

>> sorted(tree1._index.values(), key=lambda x: x.__name__)

>>> tree1._index is tree2._index
True

>>> tree1.printtree()
<class 'zodict.node.Node'>: None
  <class 'zodict.node.Node'>: a
  <class 'zodict.node.Node'>: b
  <class 'zodict.node.Node'>: c
    <class 'zodict.node.Node'>: d
    <class 'zodict.node.Node'>: e

LifecycleNode

LifecycleNode 能够根据 zope.lifecycleevent 子类发送基于对象事件的通知。

节点创建

zodict.events.NodeCreatedEvent 实现 zodict.interfaces.INodeCreatedEvent

向节点添加子节点

zodict.events.NodeAddedEvent 实现 zodict.interfaces.INodeAddedEvent

从节点删除子节点

zodict.events.NodeRemovedEvent 实现 zodict.interfaces.INodeRemovedEvent

从节点分离子节点

zodict.events.NodeDetachedEvent 实现 zodict.interfaces.INodeDetachedEvent

在节点的子类中,可以通过修改节点上的类属性 events 来交换事件类。它是一个键为 ['created', 'added', 'removed', 'detached'] 的字典。

树的线程安全锁定

NodeLifecycleNode 都不是线程安全的。应用程序构建者负责这个问题。主要原因:获取和释放锁是一个昂贵的操作。

zodict.locking 模块提供了一种机制来锁定整个树以确保线程安全。它提供了一个类和一个装饰器。该类旨在与某些节点独立使用,装饰器则用于 NodeLifecycleNode 的子类。

zodict.locking.TreeLock 是一个类似于适配器的类,用于节点。它可以在 Python > 2.6 中使用 with 语句。

>>> node = Node()
>>> with TreeLock(node):
>>>     # do something on the locked tree
>>>     node['foo'] = Node()

作为替代,它可以在旧版本的 Python 中使用 try: finally。

>>> from zodict.locking import TreeLock
>>> lock = TreeLock(node)
>>> lock.acquire()
>>> try:
>>>     # do something on the locked tree
>>>     node['bar'] = Node()
>>> finally:
>>>     lock.release()

zodict.locking.locktree 装饰器用于 Node 的 (子-) 类的方法。

>>> from zodict.locking import locktree
>>> class LockedNode(Node):
...
...     @locktree
...     def __setitem__(self, key, val):
...         super(LockedNode, self).__setitem__(key, val)

更改

版本 1.9.3

  • 提供抽象的 _Node 实现。[rnix, 2010-07-08]

  • 文档中的错误。[thet, 2010-07-06]

  • 在 except 块中导入 BBB 而不是首先尝试它。[thet, 2010-07-06]

  • 为测试目的提供 Buildout 配置。[thet, 2010-07-06]

版本 1.9.2

  • Node.__setitem__ 中的索引检查之前设置 child.__name__child.__parent__,因为在 child.keys() 调用中,子节点的键可能依赖于这些。[rnix, 2010-05-01]

  • AttributedNodeLifecycleNode 分离出来,因此现在可以使用属性而无需事件。[jensens, 2010-04-28]

版本 1.9.1

  • 添加布尔评估测试 [rnix, 2010-04-21]

  • __setattr____getattr__ 添加到 NodeAttributes 对象。[rnix, 2010-04-21]

  • 为 zope2.9 提供 BBB 兼容性 [rnix, jensens, 2010-02-17]

版本 1.9.0

  • 使 zodict 重新与 python 2.4 兼容,BBB [jensens, 2009-12-23]

  • 添加锁定测试 [rnix, 2009-12-23]

  • 重构锁定,从节点基本实现中移除树锁定。添加易于使用的锁定类和一个用于在应用程序和 Node 子类中使用的装饰器。[jensens, 2009-12-23]

  • 引入 ICallableNodeILeafIRoot 接口。[rnix, 2009-12-23]

  • 将许可证更改为 PSF [rnix, 2009-12-22]

  • 添加 zodict.node.NodeAttributes 对象。[rnix, 2009-12-22]

  • LifecycleNode 添加 attributes 属性。[rnix, 2009-12-22]

  • 添加 ILifecycleNodeINodeAttributes 接口。[rnix, 2009-12-22]

  • 修复了私有变量名称中的错误。将 "notify-suppress" 添加到 LifecycleNode 的 setitem 中。[jensens, 2009-12-22]

版本 1.8.0

  • zope.lifecycle 事件添加到新的 LifecycleNode 中。您可以使用自己的事件轻松覆盖它们。[jensens, 2009-12-21]

  • 将类 zodict 重命名为 Zodict,将模块 zodict.zodict 重命名为 zodict._zodict。这避免了导入时丑陋的冲突(包 vs. 模块 vs. 类)。1.x 版本系列中提供了 BBB 导入。[jensens, 2009-12-21]

版本 1.7.0

  • 添加 Node.detach 函数。用于节点或子树移动。出于性能原因进行此操作。[rnix, 2009-12-18]

  • Node.index 现在返回一个 NodeIndex 对象,该对象实现了 zope.interface.common.mapping.IReadMapping。此功能在节点查找之前将 uuid 实例转换为整数。因此,我们仍然符合通过 uuid 从索引返回节点的约定。[rnix, 2009-12-18]

  • Node._index 的键类型更改为 int。调用 uuid.UUID.__hash__ 函数太频繁了 [jensens, rnix, 2009-12-18]

  • 使 Node 成为线程安全的。[jensens, rnix, 2009-12-18]

版本 1.6.1

  • 使 Node 树正确合并。[rnix, 2009-12-15]

  • uuid 属性的获取器和设置器函数设置为私有。[rnix, 2009-12-15]

版本 1.6.0

  • 删除 traverser 模块。[rnix, 2009-11-28]

  • 略微改进 insertbeforeinsertafter。[rnix, 2009-11-28]

  • index 属性添加到 Node 中。允许访问内部 _index 属性。[rnix, 2009-11-28]

  • 删除 @accept@return 装饰器。只是多余的。[rnix, 2009-11-28]

版本 1.5.0

  • insertbeforeinsertafter 函数添加到 Node 中。[rnix, 2009-11-27]

  • 修复 printtree,如果 Node.__name__None。[rnix, 2009-11-20]

  • printtree 调试辅助函数添加到 Node 中。[rnix, 2009-11-09]

  • 定义自己的 Traverser 接口并减少依赖。[rnix, 2009-10-28]

  • 从 zodicts __init__ 中删除测试导入。如果未安装 interlude,则会导致导入错误。[jensens, 2009-07-16]

版本 1.4.0

  • 不允许将类作为 Node 的值。属性 __name__ 存在冲突。[jensens, 2009-05-06]

  • repr(nodeobj) 现在返回实际的类名,而不是固定的 <Node object。这在测试和使用从 Node 继承的类时非常有帮助![jensens, 2009-05-06]

  • 使测试通过 python setup.py test 运行。删除了对 zope.testing 的多余依赖。[jensens, 2009-05-06]

版本 1.3.3

  • 修复包括 BBB 的 ITraverser 接口导入。

版本 1.3.2

  • root 属性添加到 Node 中。[thet, 2009-04-24]

版本 1.3.1

  • __delitem__ 函数添加到 Node 中。[rnix, 2009-04-16]

版本 1.3

  • uuid 属性和 node 函数添加到 Node 中。[rnix, 2009-03-23]

版本 1.2

  • filtereditems 函数添加到 Node 中。[rnix, 2009-03-22]

版本 1.1

  • 添加 INode 接口和实现。[rnix, 2009-03-18]

鸣谢

项目详细信息


下载文件

下载适用于您的平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

zodict-1.9.3.tar.gz (18.0 kB 查看哈希值)

源代码

由以下支持