符合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'] 的字典。
树的线程安全锁定
Node 和 LifecycleNode 都不是线程安全的。应用程序构建者负责这个问题。主要原因:获取和释放锁是一个昂贵的操作。
zodict.locking 模块提供了一种机制来锁定整个树以确保线程安全。它提供了一个类和一个装饰器。该类旨在与某些节点独立使用,装饰器则用于 Node 或 LifecycleNode 的子类。
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]
将 AttributedNode 从 LifecycleNode 分离出来,因此现在可以使用属性而无需事件。[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]
引入 ICallableNode,ILeaf 和 IRoot 接口。[rnix, 2009-12-23]
将许可证更改为 PSF [rnix, 2009-12-22]
添加 zodict.node.NodeAttributes 对象。[rnix, 2009-12-22]
向 LifecycleNode 添加 attributes 属性。[rnix, 2009-12-22]
添加 ILifecycleNode 和 INodeAttributes 接口。[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]
略微改进 insertbefore 和 insertafter。[rnix, 2009-11-28]
将 index 属性添加到 Node 中。允许访问内部 _index 属性。[rnix, 2009-11-28]
删除 @accept 和 @return 装饰器。只是多余的。[rnix, 2009-11-28]
版本 1.5.0
将 insertbefore 和 insertafter 函数添加到 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]
鸣谢
由 Robert Niederreiter 编写 <rnix@squarewave.at>
由 Jens Klein 提供贡献和想法 <jens@bluedynamics.com>
项目详细信息
zodict-1.9.3.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | a3d3e5cbb82d0e8ded9e4c80d11b01e02367c32acab8ac3ae9ae60b9812b4dff |
|
MD5 | dce7c57b6b5e2f60d4725a4cc0400885 |
|
BLAKE2b-256 | f09faba250ff7309fafe22aa6ea28d8cfdf02088151b5a1eb4093b5e08172659 |