src/pyams_utils/registry.py
changeset 1 3f89629b9e54
child 14 a4cf46dc5634
equal deleted inserted replaced
0:16d47bd81d84 1:3f89629b9e54
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 
       
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 
       
    16 # import standard library
       
    17 import venusian
       
    18 
       
    19 # import interfaces
       
    20 from zope.component.interfaces import ComponentLookupError
       
    21 
       
    22 # import packages
       
    23 from pyramid.threadlocal import get_current_registry, get_current_request
       
    24 from zope.interface import implementedBy, providedBy
       
    25 
       
    26 
       
    27 def _get_registries():
       
    28     """Get list of component registries"""
       
    29     registry = get_current_registry()
       
    30     yield registry
       
    31     request = get_current_request()
       
    32     if (request is not None) and (request.registry != registry):
       
    33         yield request.registry
       
    34 
       
    35 
       
    36 def registered_utilities():
       
    37     """Get utilities registrations as generator"""
       
    38     for registry in _get_registries():
       
    39         for utility in registry.registeredUtilities():
       
    40             yield utility
       
    41 
       
    42 
       
    43 def query_utility(provided, name='', default=None):
       
    44     """Query utility registered with given interface"""
       
    45     for registry in _get_registries():
       
    46         utility = registry.queryUtility(provided, name, default)
       
    47         if utility is not None:
       
    48             return utility
       
    49     return default
       
    50 
       
    51 
       
    52 def get_utility(provided, name=''):
       
    53     """Get utility registered with given interface"""
       
    54     for registry in _get_registries():
       
    55         utility = registry.queryUtility(provided, name)
       
    56         if utility is not None:
       
    57             return utility
       
    58     raise ComponentLookupError(provided, name)
       
    59 
       
    60 
       
    61 def get_utilities_for(interface):
       
    62     """Get utilities registered with given interface as (name, util)"""
       
    63     for registry in _get_registries():
       
    64         for utility in registry.getUtilitiesFor(interface):
       
    65             yield utility
       
    66 
       
    67 
       
    68 def get_all_utilities_registered_for(interface):
       
    69     """Get list of registered utilities for given interface"""
       
    70     result = []
       
    71     for registry in _get_registries():
       
    72         for utilities in registry.getAllUtilitiesRegisteredFor(interface):
       
    73             result.extend(utilities)
       
    74     return result
       
    75 
       
    76 
       
    77 class utility_config(object):
       
    78     """Function or class decorator to declare a utility"""
       
    79 
       
    80     venusian = venusian
       
    81 
       
    82     def __init__(self, **settings):
       
    83         self.__dict__.update(settings)
       
    84 
       
    85     def __call__(self, wrapped):
       
    86         settings = self.__dict__.copy()
       
    87         depth = settings.pop('_depth', 0)
       
    88 
       
    89         def callback(context, name, ob):
       
    90             if type(ob) is type:
       
    91                 factory = ob
       
    92                 component = None
       
    93             else:
       
    94                 factory = None
       
    95                 component = ob
       
    96 
       
    97             provides = settings.get('provides')
       
    98             if provides is None:
       
    99                 if factory:
       
   100                     provides = list(implementedBy(factory))
       
   101                 else:
       
   102                     provides = list(providedBy(component))
       
   103                 if len(provides) == 1:
       
   104                     provides = provides[0]
       
   105                 else:
       
   106                     raise TypeError("Missing 'provides' argument")
       
   107 
       
   108             config = context.config.with_package(info.module)
       
   109             config.registry.registerUtility(component=component, factory=factory,
       
   110                                             provided=provides, name=settings.get('name', ''))
       
   111 
       
   112         info = self.venusian.attach(wrapped, callback, category='pyams_utility',
       
   113                                     depth=depth + 1)
       
   114 
       
   115         if info.scope == 'class':
       
   116             # if the decorator was attached to a method in a class, or
       
   117             # otherwise executed at class scope, we need to set an
       
   118             # 'attr' into the settings if one isn't already in there
       
   119             if settings.get('attr') is None:
       
   120                 settings['attr'] = wrapped.__name__
       
   121 
       
   122         settings['_info'] = info.codeinfo  # fbo "action_method"
       
   123         return wrapped