|
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 |
|
21 # import packages |
|
22 from zope.interface import implementedBy |
|
23 |
|
24 |
|
25 class ContextAdapter(object): |
|
26 """Context adapter""" |
|
27 |
|
28 def __init__(self, context): |
|
29 self.context = context |
|
30 |
|
31 |
|
32 class ContextRequestAdapter(object): |
|
33 """Context + request adapter""" |
|
34 |
|
35 def __init__(self, context, request): |
|
36 self.context = context |
|
37 self.request = request |
|
38 |
|
39 |
|
40 class ContextRequestViewAdapter(object): |
|
41 """Context + request + view adapter""" |
|
42 |
|
43 def __init__(self, context, request, view): |
|
44 self.context = context |
|
45 self.request = request |
|
46 self.view = view |
|
47 |
|
48 |
|
49 class adapter_config(object): |
|
50 """Function or class decorator to declare an adapter""" |
|
51 |
|
52 venusian = venusian |
|
53 |
|
54 def __init__(self, **settings): |
|
55 if 'for_' in settings: |
|
56 if settings.get('context') is None: |
|
57 settings['context'] = settings.pop('for_') |
|
58 self.__dict__.update(settings) |
|
59 |
|
60 def __call__(self, wrapped): |
|
61 settings = self.__dict__.copy() |
|
62 depth = settings.pop('_depth', 0) |
|
63 |
|
64 def callback(context, name, ob): |
|
65 adapts = settings.get('context') |
|
66 if adapts is None: |
|
67 adapts = getattr(ob, '__component_adapts__', None) |
|
68 if adapts is None: |
|
69 raise TypeError("No for argument was provided for %r and " |
|
70 "can't determine what the factory adapts." % ob) |
|
71 if not isinstance(adapts, tuple): |
|
72 adapts = (adapts,) |
|
73 |
|
74 provides = settings.get('provides') |
|
75 if provides is None: |
|
76 intfs = list(implementedBy(ob)) |
|
77 if len(intfs) == 1: |
|
78 provides = intfs[0] |
|
79 if provides is None: |
|
80 raise TypeError("Missing 'provided' argument") |
|
81 |
|
82 config = context.config.with_package(info.module) |
|
83 config.registry.registerAdapter(ob, adapts, provides, settings.get('name', '')) |
|
84 |
|
85 info = self.venusian.attach(wrapped, callback, category='pyams_adapter', |
|
86 depth=depth + 1) |
|
87 |
|
88 if info.scope == 'class': |
|
89 # if the decorator was attached to a method in a class, or |
|
90 # otherwise executed at class scope, we need to set an |
|
91 # 'attr' into the settings if one isn't already in there |
|
92 if settings.get('attr') is None: |
|
93 settings['attr'] = wrapped.__name__ |
|
94 |
|
95 settings['_info'] = info.codeinfo # fbo "action_method" |
|
96 return wrapped |