Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
212 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,247 +1,55 @@ | ||
import copy | ||
from plumber import ( | ||
plumber, | ||
Part, | ||
default, | ||
extend, | ||
finalize, | ||
plumb, | ||
) | ||
from odict.pyodict import ( | ||
_odict, | ||
_nil, | ||
) | ||
from plumber import plumber | ||
from persistent import Persistent | ||
from persistent.dict import PersistentDict | ||
from BTrees.OOBTree import OOBTree | ||
from zope.interface import implements | ||
from node.interfaces import ( | ||
INode, | ||
IAttributes, | ||
) | ||
from node.parts import ( | ||
Adopt, | ||
Nodespaces, | ||
Attributes, | ||
Order, | ||
AsAttrAccess, | ||
DefaultInit, | ||
Nodify, | ||
NodeChildValidate, | ||
Storage, | ||
) | ||
from node.utils import ( | ||
AttributeAccess, | ||
instance_property, | ||
from node.ext.zodb.interfaces import IZODBNode | ||
from node.ext.zodb.parts import ( | ||
ZODBPart, | ||
PodictStorage, | ||
OOBTodictStorage, | ||
ZODBAttributes, | ||
) | ||
from node.ext.zodb.utils import ( | ||
Podict, | ||
OOBTodict, | ||
volatile_property, | ||
) | ||
|
||
|
||
class Podict(_odict, PersistentDict): | ||
|
||
def _dict_impl(self): | ||
return PersistentDict | ||
|
||
|
||
class OOBTodict(_odict, OOBTree): | ||
|
||
def _dict_impl(self): | ||
return OOBTree | ||
|
||
def _get_lh(self): | ||
try: | ||
return self['____lh'] | ||
except KeyError: | ||
self['____lh'] = _nil | ||
return self['____lh'] | ||
|
||
def _set_lh(self, val): | ||
self['____lh'] = val | ||
|
||
lh = property(_get_lh, _set_lh) | ||
|
||
def _get_lt(self): | ||
try: | ||
return self['____lt'] | ||
except KeyError: | ||
self['____lt'] = _nil | ||
return self['____lt'] | ||
|
||
def _set_lt(self, val): | ||
self['____lt'] = val | ||
|
||
lt = property(_get_lt, _set_lt) | ||
|
||
def __getitem__(self, key): | ||
if key.startswith('____'): | ||
return self._dict_impl().__getitem__(self, key) | ||
return _odict.__getitem__(self, key) | ||
|
||
def __setitem__(self, key, val): | ||
if key.startswith('____'): | ||
# private attributes, no way to set persistent attributes on | ||
# OOBTree deriving class. | ||
self._dict_impl().__setitem__(self, key, val) | ||
else: | ||
_odict.__setitem__(self, key, val) | ||
|
||
def __repr__(self): | ||
if self: | ||
pairs = ("(%r, %r)" % (k, v) for k, v in self.iteritems()) | ||
return "OOBTodict([%s])" % ", ".join(pairs) | ||
else: | ||
return "OOBTodict()" | ||
|
||
|
||
class IZODBNode(INode): | ||
"""Marker for ZODB nodes. | ||
""" | ||
|
||
|
||
class ZODBPart(Part): | ||
"""This part requires plumbed class to inherit from Persistent. | ||
""" | ||
implements(IZODBNode) | ||
|
||
@extend | ||
@property | ||
def __parent__(self): | ||
"""Always expect _v_parent to be set, see __setattr__ and | ||
__getitem__. | ||
""" | ||
return self._v_parent | ||
|
||
@extend | ||
def __getitem__(self, key): | ||
v = self.storage[key] | ||
if INode.providedBy(v): | ||
v._v_parent = self | ||
return v | ||
|
||
@extend | ||
def __setattr__(self, name, value): | ||
"""If name is __parent__, write value to _v_parent. This avoids | ||
_p_changed to be set set by Persitent.__setattr__. Using a read/write | ||
property for __name__ won't work. | ||
""" | ||
if name == '__parent__': | ||
name = '_v_parent' | ||
Persistent.__setattr__(self, name, value) | ||
|
||
@default | ||
def __call__(self): | ||
"""Meant to be plumbed if something should happen in a particular | ||
subclass on __call__. Persisting is left to the ZODB transaction | ||
mechanism. | ||
""" | ||
pass | ||
|
||
@plumb | ||
def __setitem__(_next, self, key, value): | ||
_next(self, key, value) | ||
self.storage._p_changed = 1 | ||
|
||
@finalize | ||
def copy(self): | ||
return copy.deepcopy(self) | ||
|
||
|
||
class PodictStorage(ZODBPart, Storage): | ||
|
||
@default | ||
@instance_property | ||
def storage(self): | ||
return Podict() | ||
|
||
|
||
class OOBTodictStorage(ZODBPart, Storage): | ||
|
||
@default | ||
@instance_property | ||
def storage(self): | ||
return OOBTodict() | ||
|
||
|
||
class ZODBAttributes(Part): | ||
implements(IAttributes) | ||
|
||
attribute_access_for_attrs = default(False) | ||
attributes_factory = default(None) | ||
|
||
@finalize | ||
@property | ||
def attrs(self): | ||
try: | ||
attrs = self._attrs | ||
except AttributeError: | ||
self._attrs = attrs = self.attributes_factory(name='_attrs', | ||
parent=self) | ||
if self.attribute_access_for_attrs: | ||
return AttributeAccess(attrs) | ||
return attrs | ||
attribute_parts = ( | ||
NodeChildValidate, Adopt, DefaultInit, Nodify | ||
) | ||
node_parts = ( | ||
NodeChildValidate, Adopt, Order, AsAttrAccess, | ||
DefaultInit, Nodify, ZODBAttributes | ||
) | ||
|
||
|
||
class ZODBNodeAttributes(Persistent): | ||
__metaclass__ = plumber | ||
__plumbing__ = ( | ||
NodeChildValidate, | ||
Adopt, | ||
DefaultInit, | ||
Nodify, | ||
PodictStorage, | ||
) | ||
__plumbing__ = attribute_parts + (PodictStorage,) | ||
allow_non_node_childs = True | ||
|
||
|
||
class ZODBNode(Persistent): | ||
__metaclass__ = plumber | ||
__plumbing__ = ( | ||
NodeChildValidate, | ||
Adopt, | ||
Order, | ||
AsAttrAccess, | ||
DefaultInit, | ||
Nodify, | ||
ZODBAttributes, | ||
PodictStorage, | ||
) | ||
__plumbing__ = node_parts + (PodictStorage,) | ||
attributes_factory = ZODBNodeAttributes | ||
|
||
|
||
class OOBTNodeAttributes(Persistent): | ||
__metaclass__ = plumber | ||
__plumbing__ = ( | ||
NodeChildValidate, | ||
Adopt, | ||
DefaultInit, | ||
Nodify, | ||
OOBTodictStorage, | ||
) | ||
__plumbing__ = attribute_parts + (OOBTodictStorage,) | ||
allow_non_node_childs = True | ||
|
||
|
||
class OOBTNode(Persistent): | ||
__metaclass__ = plumber | ||
__plumbing__ = ( | ||
NodeChildValidate, | ||
Adopt, | ||
Order, | ||
AsAttrAccess, | ||
DefaultInit, | ||
Nodify, | ||
ZODBAttributes, | ||
OOBTodictStorage, | ||
) | ||
attributes_factory = OOBTNodeAttributes | ||
|
||
|
||
def volatile_property(func): | ||
"""Like ``node.utils.instance_property``, but sets instance attribute | ||
with '_v_' prefix. | ||
""" | ||
def wrapper(self): | ||
attribute_name = '_v_%s' % func.__name__ | ||
if not hasattr(self, attribute_name): | ||
setattr(self, attribute_name, func(self)) | ||
return getattr(self, attribute_name) | ||
wrapper.__doc__ = func.__doc__ | ||
return property(wrapper) | ||
__plumbing__ = node_parts + (OOBTodictStorage,) | ||
attributes_factory = OOBTNodeAttributes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from node.interfaces import INode | ||
|
||
|
||
class IZODBNode(INode): | ||
"""Marker for ZODB nodes. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import copy | ||
from plumber import ( | ||
Part, | ||
default, | ||
extend, | ||
finalize, | ||
plumb, | ||
) | ||
from persistent import Persistent | ||
from zope.interface import implements | ||
from node.interfaces import ( | ||
INode, | ||
IAttributes, | ||
) | ||
from node.parts import Storage | ||
from node.utils import ( | ||
AttributeAccess, | ||
instance_property, | ||
) | ||
from node.ext.zodb.interfaces import IZODBNode | ||
from node.ext.zodb.utils import ( | ||
Podict, | ||
OOBTodict, | ||
) | ||
|
||
|
||
class ZODBPart(Part): | ||
"""This part requires plumbed class to inherit from Persistent. | ||
""" | ||
implements(IZODBNode) | ||
|
||
@extend | ||
@property | ||
def __parent__(self): | ||
"""Always expect _v_parent to be set, see __setattr__ and | ||
__getitem__. | ||
""" | ||
return self._v_parent | ||
|
||
@extend | ||
def __getitem__(self, key): | ||
v = self.storage[key] | ||
if INode.providedBy(v): | ||
v._v_parent = self | ||
return v | ||
|
||
@extend | ||
def __setattr__(self, name, value): | ||
"""If name is __parent__, write value to _v_parent. This avoids | ||
_p_changed to be set set by Persitent.__setattr__. Using a read/write | ||
property for __name__ won't work. | ||
""" | ||
if name == '__parent__': | ||
name = '_v_parent' | ||
Persistent.__setattr__(self, name, value) | ||
|
||
@default | ||
def __call__(self): | ||
"""Meant to be plumbed if something should happen in a particular | ||
subclass on __call__. Persisting is left to the ZODB transaction | ||
mechanism. | ||
""" | ||
pass | ||
|
||
@plumb | ||
def __setitem__(_next, self, key, value): | ||
_next(self, key, value) | ||
self.storage._p_changed = 1 | ||
|
||
@finalize | ||
def copy(self): | ||
return copy.deepcopy(self) | ||
|
||
|
||
class PodictStorage(ZODBPart, Storage): | ||
|
||
@default | ||
@instance_property | ||
def storage(self): | ||
return Podict() | ||
|
||
|
||
class OOBTodictStorage(ZODBPart, Storage): | ||
|
||
@default | ||
@instance_property | ||
def storage(self): | ||
return OOBTodict() | ||
|
||
|
||
class ZODBAttributes(Part): | ||
implements(IAttributes) | ||
|
||
attribute_access_for_attrs = default(False) | ||
attributes_factory = default(None) | ||
|
||
@finalize | ||
@property | ||
def attrs(self): | ||
try: | ||
attrs = self._attrs | ||
except AttributeError: | ||
self._attrs = attrs = self.attributes_factory(name='_attrs', | ||
parent=self) | ||
if self.attribute_access_for_attrs: | ||
return AttributeAccess(attrs) | ||
return attrs |
Oops, something went wrong.