1
2 r"""
3 :Copyright:
4
5 Copyright 2006 - 2015
6 Andr\xe9 Malo or his licensors, as applicable
7
8 :License:
9
10 Licensed under the Apache License, Version 2.0 (the "License");
11 you may not use this file except in compliance with the License.
12 You may obtain a copy of the License at
13
14 http://www.apache.org/licenses/LICENSE-2.0
15
16 Unless required by applicable law or agreed to in writing, software
17 distributed under the License is distributed on an "AS IS" BASIS,
18 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 See the License for the specific language governing permissions and
20 limitations under the License.
21
22 ================
23 Misc Utilities
24 ================
25
26 Misc utilities.
27 """
28 if __doc__:
29
30 __doc__ = __doc__.encode('ascii').decode('unicode_escape')
31 __author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
32 __docformat__ = "restructuredtext en"
33
34 import inspect as _inspect
35
36
38 """
39 Determine all public names in space
40
41 :Parameters:
42 `space` : ``dict``
43 Name space to inspect
44
45 :Return: List of public names
46 :Rtype: ``list``
47 """
48 if '__all__' in space:
49 return list(space['__all__'])
50 return [key for key in space.keys() if not key.startswith('_')]
51
52
54 """
55 Property with improved docs handling
56
57 :Parameters:
58 `func` : ``callable``
59 The function providing the property parameters. It takes no arguments
60 as returns a dict containing the keyword arguments to be defined for
61 ``property``. The documentation is taken out the function by default,
62 but can be overridden in the returned dict.
63
64 :Return: The requested property
65 :Rtype: ``property``
66 """
67
68
69 kwargs = func()
70 kwargs.setdefault('doc', func.__doc__)
71 kwargs = kwargs.get
72 return property(
73 fget=kwargs('fget'),
74 fset=kwargs('fset'),
75 fdel=kwargs('fdel'),
76 doc=kwargs('doc'),
77 )
78
79
81 """
82 Create decorator for designating decorators.
83
84 :Parameters:
85 `decorated` : function
86 Function to decorate
87
88 `extra` : ``dict``
89 Dict of consumed keyword parameters (not existing in the originally
90 decorated function), mapping to their defaults. If omitted or
91 ``None``, no extra keyword parameters are consumed. The arguments
92 must be consumed by the actual decorator function.
93
94 :Return: Decorator
95 :Rtype: ``callable``
96 """
97 def flat_names(args):
98 """ Create flat list of argument names """
99 for arg in args:
100 if isinstance(arg, basestring):
101 yield arg
102 else:
103 for arg in flat_names(arg):
104 yield arg
105 name = decorated.__name__
106 try:
107 dargspec = argspec = _inspect.getargspec(decorated)
108 except TypeError:
109 dargspec = argspec = ([], 'args', 'kwargs', None)
110 if extra:
111 keys = extra.keys()
112 argspec[0].extend(keys)
113 defaults = list(argspec[3] or ())
114 for key in keys:
115 defaults.append(extra[key])
116 argspec = (argspec[0], argspec[1], argspec[2], defaults)
117
118
119
120
121 counter, proxy_name = -1, 'proxy'
122 names = dict.fromkeys(flat_names(argspec[0]))
123 names[name] = None
124 while proxy_name in names:
125 counter += 1
126 proxy_name = 'proxy%s' % counter
127
128 def inner(decorator):
129 """ Actual decorator """
130
131 space = {proxy_name: decorator}
132 if argspec[3]:
133 kwnames = argspec[0][-len(argspec[3]):]
134 else:
135 kwnames = None
136 passed = _inspect.formatargspec(
137 argspec[0], argspec[1], argspec[2], kwnames,
138 formatvalue=lambda value: '=' + value
139 )
140 exec "def %s%s: return %s%s" % (
141 name, _inspect.formatargspec(*argspec), proxy_name, passed
142 ) in space
143 wrapper = space[name]
144 wrapper.__dict__ = decorated.__dict__
145 wrapper.__doc__ = decorated.__doc__
146 if extra and decorated.__doc__ is not None:
147 if not decorated.__doc__.startswith('%s(' % name):
148 wrapper.__doc__ = "%s%s\n\n%s" % (
149 name,
150 _inspect.formatargspec(*dargspec),
151 decorated.__doc__,
152 )
153 return wrapper
154
155 return inner
156