Changed local registry management method
authorThierry Florac <tflorac@ulthar.net>
Sat, 14 Mar 2015 13:49:03 +0100
changeset 20 4bbf6181e1cf
parent 19 378978d7c534
child 21 b1b92e017581
Changed local registry management method
src/pyams_utils/registry.py
--- a/src/pyams_utils/registry.py	Sat Mar 14 13:48:37 2015 +0100
+++ b/src/pyams_utils/registry.py	Sat Mar 14 13:49:03 2015 +0100
@@ -17,35 +17,76 @@
 import logging
 logger = logging.getLogger('PyAMS (utils)')
 
+import threading
 import venusian
 
 # import interfaces
-from zope.component.interfaces import ComponentLookupError
+from pyramid.interfaces import INewRequest
+from zope.component.interfaces import ComponentLookupError, ISite
+from zope.traversing.interfaces import IBeforeTraverseEvent
 
 # import packages
-from pyramid.threadlocal import get_current_registry, get_current_request
+from pyramid.events import subscriber
+from pyramid.threadlocal import manager
 from zope.interface import implementedBy, providedBy
 
 
-def _get_registries():
-    """Get list of component registries"""
-    registry = get_current_registry()
-    yield registry
-    request = get_current_request()
-    if (request is not None) and (request.registry != registry):
-        yield request.registry
+class LocalRegistry(threading.local):
+    """Local registry"""
+
+    _registry = None
+
+    def get_registry(self):
+        return self._registry
+
+    def set_registry(self, registry):
+        self._registry = registry
+
+local_registry = LocalRegistry()
+
+
+def get_local_registry():
+    """Get local registry"""
+    return local_registry.get_registry()
+
+
+def set_local_registry(registry):
+    """Define local registry"""
+    local_registry.set_registry(registry)
+
+
+@subscriber(INewRequest)
+def handle_new_request(event):
+    set_local_registry(None)
+
+
+@subscriber(IBeforeTraverseEvent, context_selector=ISite)
+def handle_site_before_traverse(event):
+    """Define local registry when an object implementing ISite is traversed"""
+    set_local_registry(event.object.getSiteManager())
+
+
+def get_registries():
+    """Get iterator on components registries"""
+    registry = local_registry.get_registry()
+    if registry is not None:
+        yield registry
+    for entry in reversed(manager.stack):
+        registry = entry.get('registry')
+        if entry is not None:
+            yield registry
 
 
 def registered_utilities():
     """Get utilities registrations as generator"""
-    for registry in _get_registries():
+    for registry in get_registries():
         for utility in registry.registeredUtilities():
             yield utility
 
 
 def query_utility(provided, name='', default=None):
     """Query utility registered with given interface"""
-    for registry in _get_registries():
+    for registry in get_registries():
         utility = registry.queryUtility(provided, name, default)
         if utility is not None:
             return utility
@@ -54,7 +95,7 @@
 
 def get_utility(provided, name=''):
     """Get utility registered with given interface"""
-    for registry in _get_registries():
+    for registry in get_registries():
         utility = registry.queryUtility(provided, name)
         if utility is not None:
             return utility
@@ -63,7 +104,7 @@
 
 def get_utilities_for(interface):
     """Get utilities registered with given interface as (name, util)"""
-    for registry in _get_registries():
+    for registry in get_registries():
         for utility in registry.getUtilitiesFor(interface):
             yield utility
 
@@ -71,7 +112,7 @@
 def get_all_utilities_registered_for(interface):
     """Get list of registered utilities for given interface"""
     result = []
-    for registry in _get_registries():
+    for registry in get_registries():
         for utilities in registry.getAllUtilitiesRegisteredFor(interface):
             result.append(utilities)
     return result