Michael Merickel
2018-10-19 d579f2104de139e0b0fc5d6c81aabb2f826e5e54
commit | author | age
d7f34b 1 from zope.interface import implementer
MM 2
ee117e 3 from pyramid.interfaces import (
CM 4     IDefaultRootFactory,
0bee84 5     IExecutionPolicy,
ee117e 6     IRequestFactory,
1236de 7     IResponseFactory,
d7f34b 8     IRequestExtensions,
ee117e 9     IRootFactory,
CM 10     ISessionFactory,
0c29cf 11 )
5bf23f 12
0bee84 13 from pyramid.router import default_execution_policy
5bf23f 14 from pyramid.traversal import DefaultRootFactory
d8d3a9 15
0c29cf 16 from pyramid.util import get_callable_name, InstancePropertyHelper
1e0d64 17
d579f2 18 from pyramid.config.actions import action_method
0c29cf 19
5bf23f 20
CM 21 class FactoriesConfiguratorMixin(object):
22     @action_method
ea824f 23     def set_root_factory(self, factory):
5bf23f 24         """ Add a :term:`root factory` to the current configuration
CM 25         state.  If the ``factory`` argument is ``None`` a default root
adfc23 26         factory will be registered.
CM 27
012b97 28         .. note::
M 29
30            Using the ``root_factory`` argument to the
31            :class:`pyramid.config.Configurator` constructor can be used to
32            achieve the same purpose.
adfc23 33         """
5bf23f 34         factory = self.maybe_dotted(factory)
CM 35         if factory is None:
36             factory = DefaultRootFactory
1e0d64 37
5bf23f 38         def register():
CM 39             self.registry.registerUtility(factory, IRootFactory)
1e0d64 40             self.registry.registerUtility(factory, IDefaultRootFactory)  # b/c
3b5ccb 41
0c29cf 42         intr = self.introspectable(
MM 43             'root factories',
44             None,
45             self.object_description(factory),
46             'root factory',
47         )
3b5ccb 48         intr['factory'] = factory
CM 49         self.action(IRootFactory, register, introspectables=(intr,))
5bf23f 50
1e0d64 51     _set_root_factory = set_root_factory  # bw compat
ea824f 52
5bf23f 53     @action_method
5e92f3 54     def set_session_factory(self, factory):
5bf23f 55         """
637bda 56         Configure the application with a :term:`session factory`.  If this
5e92f3 57         method is called, the ``factory`` argument must be a session
637bda 58         factory callable or a :term:`dotted Python name` to that factory.
5bf23f 59
012b97 60         .. note::
M 61
62            Using the ``session_factory`` argument to the
63            :class:`pyramid.config.Configurator` constructor can be used to
64            achieve the same purpose.
5bf23f 65         """
5e92f3 66         factory = self.maybe_dotted(factory)
1e0d64 67
5bf23f 68         def register():
5e92f3 69             self.registry.registerUtility(factory, ISessionFactory)
0c29cf 70
MM 71         intr = self.introspectable(
72             'session factory',
73             None,
74             self.object_description(factory),
75             'session factory',
76         )
5e92f3 77         intr['factory'] = factory
3b5ccb 78         self.action(ISessionFactory, register, introspectables=(intr,))
5bf23f 79
CM 80     @action_method
81     def set_request_factory(self, factory):
82         """ The object passed as ``factory`` should be an object (or a
83         :term:`dotted Python name` which refers to an object) which
84         will be used by the :app:`Pyramid` router to create all
85         request objects.  This factory object must have the same
86         methods and attributes as the
87         :class:`pyramid.request.Request` class (particularly
88         ``__call__``, and ``blank``).
89
e0c4bd 90         See :meth:`pyramid.config.Configurator.add_request_method`
6c2e8f 91         for a less intrusive way to extend the request objects with
e0c4bd 92         custom methods and properties.
6c2e8f 93
012b97 94         .. note::
M 95
96            Using the ``request_factory`` argument to the
5bf23f 97            :class:`pyramid.config.Configurator` constructor
CM 98            can be used to achieve the same purpose.
99         """
100         factory = self.maybe_dotted(factory)
1e0d64 101
5bf23f 102         def register():
CM 103             self.registry.registerUtility(factory, IRequestFactory)
0c29cf 104
MM 105         intr = self.introspectable(
106             'request factory',
107             None,
108             self.object_description(factory),
109             'request factory',
110         )
3b5ccb 111         intr['factory'] = factory
CM 112         self.action(IRequestFactory, register, introspectables=(intr,))
5bf23f 113
74d503 114     @action_method
1236de 115     def set_response_factory(self, factory):
JA 116         """ The object passed as ``factory`` should be an object (or a
117         :term:`dotted Python name` which refers to an object) which
118         will be used by the :app:`Pyramid` as the default response
da5f5f 119         objects. The factory should conform to the
MM 120         :class:`pyramid.interfaces.IResponseFactory` interface.
1236de 121
JA 122         .. note::
123
124            Using the ``response_factory`` argument to the
125            :class:`pyramid.config.Configurator` constructor
126            can be used to achieve the same purpose.
127         """
128         factory = self.maybe_dotted(factory)
129
130         def register():
131             self.registry.registerUtility(factory, IResponseFactory)
132
0c29cf 133         intr = self.introspectable(
MM 134             'response factory',
135             None,
136             self.object_description(factory),
137             'response factory',
138         )
1236de 139         intr['factory'] = factory
JA 140         self.action(IResponseFactory, register, introspectables=(intr,))
141
142     @action_method
0c29cf 143     def add_request_method(
MM 144         self, callable=None, name=None, property=False, reify=False
145     ):
d7f34b 146         """ Add a property or method to the request object.
74d503 147
d7f34b 148         When adding a method to the request, ``callable`` may be any
MM 149         function that receives the request object as the first
150         parameter. If ``name`` is ``None`` then it will be computed
151         from the name of the ``callable``.
152
153         When adding a property to the request, ``callable`` can either
154         be a callable that accepts the request as its single positional
f32dac 155         parameter, or it can be a property descriptor. If ``callable`` is
e33241 156         a property descriptor, it has to be an instance of a class which is
f32dac 157         a subclass of ``property``. If ``name`` is ``None``, the name of
JW 158         the property will be computed from the name of the ``callable``.
74d503 159
MM 160         If the ``callable`` is a property descriptor a ``ValueError``
161         will be raised if ``name`` is ``None`` or ``reify`` is ``True``.
162
163         See :meth:`pyramid.request.Request.set_property` for more
d7f34b 164         details on ``property`` vs ``reify``. When ``reify`` is
MM 165         ``True``, the value of ``property`` is assumed to also be
166         ``True``.
167
168         In all cases, ``callable`` may also be a
169         :term:`dotted Python name` which refers to either a callable or
170         a property descriptor.
171
172         If ``callable`` is ``None`` then the method is only used to
173         assist in conflict detection between different addons requesting
174         the same attribute on the request object.
74d503 175
MM 176         This is the recommended method for extending the request object
177         and should be used in favor of providing a custom request
178         factory via
179         :meth:`pyramid.config.Configurator.set_request_factory`.
180
d7f34b 181         .. versionadded:: 1.4
74d503 182         """
d7f34b 183         if callable is not None:
MM 184             callable = self.maybe_dotted(callable)
74d503 185
d7f34b 186         property = property or reify
MM 187         if property:
04cc91 188             name, callable = InstancePropertyHelper.make_property(
0c29cf 189                 callable, name=name, reify=reify
MM 190             )
d7f34b 191         elif name is None:
MM 192             name = callable.__name__
1e0d64 193         else:
JA 194             name = get_callable_name(name)
74d503 195
MM 196         def register():
d7f34b 197             exts = self.registry.queryUtility(IRequestExtensions)
74d503 198
d7f34b 199             if exts is None:
MM 200                 exts = _RequestExtensions()
201                 self.registry.registerUtility(exts, IRequestExtensions)
74d503 202
d7f34b 203             plist = exts.descriptors if property else exts.methods
b940e4 204             plist[name] = callable
74d503 205
d7f34b 206         if callable is None:
MM 207             self.action(('request extensions', name), None)
208         elif property:
0c29cf 209             intr = self.introspectable(
MM 210                 'request extensions',
211                 name,
212                 self.object_description(callable),
213                 'request property',
214             )
d7f34b 215             intr['callable'] = callable
MM 216             intr['property'] = True
217             intr['reify'] = reify
0c29cf 218             self.action(
MM 219                 ('request extensions', name), register, introspectables=(intr,)
220             )
d7f34b 221         else:
0c29cf 222             intr = self.introspectable(
MM 223                 'request extensions',
224                 name,
225                 self.object_description(callable),
226                 'request method',
227             )
d7f34b 228             intr['callable'] = callable
MM 229             intr['property'] = False
230             intr['reify'] = False
0c29cf 231             self.action(
MM 232                 ('request extensions', name), register, introspectables=(intr,)
233             )
ba0593 234
0bee84 235     @action_method
MM 236     def set_execution_policy(self, policy):
237         """
238         Override the :app:`Pyramid` :term:`execution policy` in the
239         current configuration.  The ``policy`` argument must be an instance
240         of an :class:`pyramid.interfaces.IExecutionPolicy` or a
241         :term:`dotted Python name` that points at an instance of an
242         execution policy.
243
244         """
245         policy = self.maybe_dotted(policy)
246         if policy is None:
247             policy = default_execution_policy
248
249         def register():
250             self.registry.registerUtility(policy, IExecutionPolicy)
251
0c29cf 252         intr = self.introspectable(
MM 253             'execution policy',
254             None,
255             self.object_description(policy),
256             'execution policy',
257         )
0bee84 258         intr['policy'] = policy
MM 259         self.action(IExecutionPolicy, register, introspectables=(intr,))
260
1e0d64 261
d7f34b 262 @implementer(IRequestExtensions)
MM 263 class _RequestExtensions(object):
264     def __init__(self):
b940e4 265         self.descriptors = {}
MM 266         self.methods = {}