This repository has been archived by the owner on May 13, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
An initial stab at implementing annotations and dublin core for Mongo.
Instead of storing annotations in an attribute "__annotations__", we'll store annotations directly on the object, which makes for a much nicer Mongo document. I changed the dublin core implementation to not even worry about annotations and just store an attribute directly on the object.
- Loading branch information
Showing
2 changed files
with
148 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,92 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2013 Zope Foundation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
"""Mongo Annotations Implementation.""" | ||
from persistent.dict import PersistentDict | ||
from zope import component, interface | ||
from zope.annotation import interfaces | ||
|
||
try: | ||
from UserDict import DictMixin | ||
except ImportError: | ||
from collections import MutableMapping as DictMixin | ||
|
||
class IMongoAttributeAnnotatable(interfaces.IAnnotatable): | ||
"""Marker indicating that annotations can be stored on an attribute. | ||
This is a marker interface giving permission for an `IAnnotations` | ||
adapter to store data in an attribute named `__annotations__`. | ||
""" | ||
|
||
def normalize_key(key): | ||
return key.replace('.', '_') | ||
|
||
@interface.implementer(interfaces.IAnnotations) | ||
@component.adapter(IMongoAttributeAnnotatable) | ||
class AttributeAnnotations(DictMixin): | ||
"""Store annotations on an object | ||
Store annotations in the `__annotations__` attribute on a | ||
`IAttributeAnnotatable` object. | ||
""" | ||
|
||
def __init__(self, obj, context=None): | ||
self.obj = obj | ||
|
||
def __bool__(self): | ||
return True | ||
|
||
__nonzero__ = __bool__ | ||
|
||
def get(self, key, default=None): | ||
"""See zope.annotation.interfaces.IAnnotations""" | ||
key = normalize_key(key) | ||
return getattr(self.obj, key, default) | ||
|
||
def __getitem__(self, key): | ||
key = normalize_key(key) | ||
try: | ||
return getattr(self.obj, key) | ||
except AttributeError: | ||
raise KeyError(key) | ||
|
||
def keys(self): | ||
annotations = getattr(self.obj, self.ATTR_NAME, None) | ||
if annotations is None: | ||
return [] | ||
|
||
return annotations.keys() | ||
|
||
def __iter__(self): | ||
annotations = getattr(self.obj, self.ATTR_NAME, None) | ||
if annotations is None: | ||
return iter([]) | ||
|
||
return iter(annotations) | ||
|
||
def __len__(self): | ||
raise NotImplementedError | ||
|
||
def __setitem__(self, key, value): | ||
"""See zope.annotation.interfaces.IAnnotations""" | ||
key = normalize_key(key) | ||
setattr(self.obj, key, value) | ||
|
||
def __delitem__(self, key): | ||
"""See zope.app.interfaces.annotation.IAnnotations""" | ||
key = normalize_key(key) | ||
try: | ||
delattr(self.obj, key) | ||
except AttributeError: | ||
raise KeyError(key) |
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,56 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2011 Zope Foundation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
"""Zope Dublin Core Mongo Backend Storage""" | ||
from UserDict import DictMixin | ||
|
||
import zope.interface | ||
from zope.location import Location | ||
from zope.dublincore.interfaces import IWriteZopeDublinCore | ||
from zope.dublincore.zopedublincore import ZopeDublinCore | ||
from zope.security.proxy import removeSecurityProxy | ||
|
||
class DCDataWrapper(DictMixin): | ||
|
||
def __init__(self, data): | ||
self.data = data | ||
|
||
def __getitem__(self, key): | ||
return self.data[key.replace('.', '_')] | ||
|
||
def __setitem__(self, key, value): | ||
self.data[key.replace('.', '_')] = value | ||
|
||
def __delitem__(self, key): | ||
del self.data[key.replace('.', '_')] | ||
|
||
def keys(self): | ||
return [k.replace('_', '.') for k in self.data.keys()] | ||
|
||
|
||
@zope.interface.implementer(IWriteZopeDublinCore) | ||
class ZDCAnnotatableAdapter(ZopeDublinCore, Location): | ||
"""Adapt annotatable objects to Zope Dublin Core.""" | ||
DCKEY = 'dc' | ||
|
||
def __init__(self, context): | ||
self.__parent__ = context | ||
self.__name__ = self.DCKEY | ||
naked = removeSecurityProxy(context) | ||
if not hasattr(naked, self.__name__): | ||
setattr(naked, self.__name__, {}) | ||
dcdata = DCDataWrapper(getattr(naked, self.__name__)) | ||
super(ZDCAnnotatableAdapter, self).__init__(dcdata) | ||
|
||
def _changed(self): | ||
self.__parent__._p_changed = True |