|
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 |