14 |
14 |
15 This module provides the "provider:" TALES expression, which allows inclusion of any registered |
15 This module provides the "provider:" TALES expression, which allows inclusion of any registered |
16 content provider into a Chameleon or ZPT template. |
16 content provider into a Chameleon or ZPT template. |
17 """ |
17 """ |
18 |
18 |
|
19 import inspect |
19 import re |
20 import re |
20 |
21 |
21 from chameleon.astutil import Symbol |
22 from chameleon.astutil import Symbol |
22 from chameleon.tales import StringExpr |
23 from chameleon.tales import StringExpr |
23 from pyramid_zope_request import PyramidPublisherRequest |
24 from pyramid_zope_request import PyramidPublisherRequest |
24 from zope.contentprovider.interfaces import BeforeUpdateEvent, ContentProviderLookupError, \ |
25 from zope.contentprovider.interfaces import BeforeUpdateEvent, ContentProviderLookupError, \ |
25 IContentProvider |
26 IContentProvider |
26 from zope.contentprovider.tales import addTALNamespaceData |
27 from zope.contentprovider.tales import addTALNamespaceData |
27 from zope.location.interfaces import ILocation |
28 from zope.location.interfaces import ILocation |
28 |
29 |
|
30 from pyams_utils.factory import is_interface |
29 from pyams_utils.tales import ContextExprMixin |
31 from pyams_utils.tales import ContextExprMixin |
30 |
32 |
31 |
33 |
32 __docformat__ = 'restructuredtext' |
34 __docformat__ = 'restructuredtext' |
33 |
35 |
103 name = match.groups()[0] |
105 name = match.groups()[0] |
104 else: |
106 else: |
105 raise ContentProviderLookupError(name) |
107 raise ContentProviderLookupError(name) |
106 |
108 |
107 registry = request.registry |
109 registry = request.registry |
108 provider = registry.queryMultiAdapter((context, request, view), IContentProvider, name=name) |
110 |
|
111 # we can look into request annotations to check if a provider implementation has already |
|
112 # been provided during traversal; if not, a simple adapter lookup is done |
|
113 provider = request.annotations.get('provider:{}:factory'.format(name)) |
|
114 if isinstance(provider, dict): |
|
115 for intf, factory in provider.items(): |
|
116 if (is_interface(intf) and intf.providedBy(context)) or \ |
|
117 (inspect.isclass(intf) and isinstance(context, intf)): |
|
118 provider = factory |
|
119 break |
|
120 else: |
|
121 provider = None |
|
122 if callable(provider): |
|
123 provider = provider(context, request, view) |
|
124 if provider is None: |
|
125 provider = registry.queryMultiAdapter((context, request, view), IContentProvider, |
|
126 name=name) |
109 |
127 |
110 # raise an exception if the provider was not found. |
128 # raise an exception if the provider was not found. |
111 if provider is None: |
129 if provider is None: |
112 raise ContentProviderLookupError(name) |
130 raise ContentProviderLookupError(name) |
113 |
131 |