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