src/pyams_utils/adapter.py
changeset 177 d9c6a2a99acf
parent 140 a10c588dc6a3
child 179 9fe970c45c7b
--- a/src/pyams_utils/adapter.py	Wed May 09 14:05:08 2018 +0200
+++ b/src/pyams_utils/adapter.py	Fri May 11 15:35:29 2018 +0200
@@ -28,9 +28,13 @@
 import venusian
 
 # import interfaces
+from zope.annotation.interfaces import IAnnotations
 
 # import packages
+from pyams_utils.registry import get_current_registry
 from zope.interface import implementedBy
+from zope.lifecycleevent import ObjectCreatedEvent
+from zope.location import locate as zope_locate
 
 
 class ContextAdapter(object):
@@ -125,3 +129,29 @@
 
         settings['_info'] = info.codeinfo  # fbo "action_method"
         return wrapped
+
+
+def get_annotation_adapter(context, key, factory, notify=True, locate=True, parent=None, name=None):
+    """Get an adapter via object's annotations, creating it if not existent
+    
+    :param object context: context object which should be adapted
+    :param str key: annotations key to look for
+    :param factory: if annotations key is not found, this is the factory which will be used to
+        create a new object
+    :param bool notify: if 'False', no notification event will be sent on object creation
+    :param bool locate: if 'False', the new object is not attached to any parent
+    :param object parent: parent to which new object is attached
+    :param str name: if locate is not False, this is the name with which the new object is attached
+        to it's parent.
+    """
+    annotations = IAnnotations(context, None)
+    if annotations is None:
+        return None
+    adapter = annotations.get(key)
+    if adapter is None:
+        adapter = annotations[key] = factory()
+        if notify:
+            get_current_registry().notify(ObjectCreatedEvent(adapter))
+        if locate:
+            zope_locate(adapter, context if parent is None else parent, name)
+    return adapter