Michael Merickel
2018-10-18 e4c0570d5c67ddf0ad9502169b59475ba0784d82
commit | author | age
5bf23f 1 import inspect
CM 2 import logging
3 import os
c15cbc 4 import threading
5bf23f 5 import venusian
ea824f 6
CM 7 from webob.exc import WSGIHTTPException as WebobWSGIHTTPException
8
3b5ccb 9 from pyramid.interfaces import (
CM 10     IDebugLogger,
11     IExceptionResponse,
95f766 12     IPredicateList,
568a02 13     PHASE0_CONFIG,
95f766 14     PHASE1_CONFIG,
568a02 15     PHASE2_CONFIG,
MM 16     PHASE3_CONFIG,
0c29cf 17 )
5bf23f 18
cfbbd6 19 from pyramid.asset import resolve_asset_spec
ee117e 20
66da9b 21 from pyramid.authorization import ACLAuthorizationPolicy
ee117e 22
e4c057 23 from pyramid.compat import text_, string_types
ee117e 24
5bf23f 25 from pyramid.events import ApplicationCreated
ee117e 26
e4c057 27 from pyramid.exceptions import ConfigurationError
ee117e 28
5bf23f 29 from pyramid.httpexceptions import default_exceptionresponse_view
ee117e 30
0c29cf 31 from pyramid.path import caller_package, package_of
ee117e 32
e4c057 33 from pyramid.registry import Introspectable, Introspector, Registry
ee117e 34
cfbbd6 35 from pyramid.router import Router
ee117e 36
5bf23f 37 from pyramid.settings import aslist
ee117e 38
5bf23f 39 from pyramid.threadlocal import manager
ee117e 40
0c29cf 41 from pyramid.util import WeakOrderedSet, object_description
52fde9 42
e4c057 43 from pyramid.config.util import PredicateList, action_method, not_
5bf23f 44
e4c057 45 from pyramid.config.actions import ActionConfiguratorMixin
ea046b 46 from pyramid.config.adapters import AdaptersConfiguratorMixin
CM 47 from pyramid.config.assets import AssetsConfiguratorMixin
48 from pyramid.config.factories import FactoriesConfiguratorMixin
49 from pyramid.config.i18n import I18NConfiguratorMixin
50 from pyramid.config.rendering import RenderingConfiguratorMixin
51 from pyramid.config.routes import RoutesConfiguratorMixin
52 from pyramid.config.security import SecurityConfiguratorMixin
53 from pyramid.config.settings import SettingsConfiguratorMixin
5bf23f 54 from pyramid.config.testing import TestingConfiguratorMixin
CM 55 from pyramid.config.tweens import TweensConfiguratorMixin
56 from pyramid.config.views import ViewsConfiguratorMixin
57 from pyramid.config.zca import ZCAConfiguratorMixin
e6c2d2 58
56df90 59 from pyramid.path import DottedNameResolver
CM 60
e6c2d2 61 empty = text_('')
e49638 62 _marker = object()
5bf23f 63
52fde9 64 not_ = not_  # api
32333e 65
568a02 66 PHASE0_CONFIG = PHASE0_CONFIG  # api
MM 67 PHASE1_CONFIG = PHASE1_CONFIG  # api
68 PHASE2_CONFIG = PHASE2_CONFIG  # api
69 PHASE3_CONFIG = PHASE3_CONFIG  # api
32333e 70
0c29cf 71
5bf23f 72 class Configurator(
e4c057 73     ActionConfiguratorMixin,
5bf23f 74     TestingConfiguratorMixin,
CM 75     TweensConfiguratorMixin,
76     SecurityConfiguratorMixin,
77     ViewsConfiguratorMixin,
78     RoutesConfiguratorMixin,
79     ZCAConfiguratorMixin,
80     I18NConfiguratorMixin,
81     RenderingConfiguratorMixin,
82     AssetsConfiguratorMixin,
83     SettingsConfiguratorMixin,
84     FactoriesConfiguratorMixin,
85     AdaptersConfiguratorMixin,
0c29cf 86 ):
5bf23f 87     """
CM 88     A Configurator is used to configure a :app:`Pyramid`
89     :term:`application registry`.
90
134ef7 91     The Configurator lifecycle can be managed by using a context manager to
MM 92     automatically handle calling :meth:`pyramid.config.Configurator.begin` and
93     :meth:`pyramid.config.Configurator.end` as well as
94     :meth:`pyramid.config.Configurator.commit`.
95
96     .. code-block:: python
97
98         with Configurator(settings=settings) as config:
99             config.add_route('home', '/')
100             app = config.make_wsgi_app()
101
0bf091 102     If the ``registry`` argument is not ``None``, it must
adfc23 103     be an instance of the :class:`pyramid.registry.Registry` class
CM 104     representing the registry to configure.  If ``registry`` is ``None``, the
105     configurator will create a :class:`pyramid.registry.Registry` instance
106     itself; it will also perform some default configuration that would not
107     otherwise be done.  After its construction, the configurator may be used
108     to add further configuration to the registry.
5bf23f 109
60270f 110     .. warning:: If ``registry`` is assigned the above-mentioned class
TL 111        instance, all other constructor arguments are ignored,
112        with the exception of ``package``.
5bf23f 113
adfc23 114     If the ``package`` argument is passed, it must be a reference to a Python
CM 115     :term:`package` (e.g. ``sys.modules['thepackage']``) or a :term:`dotted
116     Python name` to the same.  This value is used as a basis to convert
117     relative paths passed to various configuration methods, such as methods
118     which accept a ``renderer`` argument, into absolute paths.  If ``None``
119     is passed (the default), the package is assumed to be the Python package
120     in which the *caller* of the ``Configurator`` constructor lives.
5bf23f 121
ae6c88 122     If the ``root_package`` is passed, it will propagate through the
MM 123     configuration hierarchy as a way for included packages to locate
124     resources relative to the package in which the main ``Configurator`` was
125     created. If ``None`` is passed (the default), the ``root_package`` will
126     be derived from the ``package`` argument. The ``package`` attribute is
127     always pointing at the package being included when using :meth:`.include`,
128     whereas the ``root_package`` does not change.
129
5bf23f 130     If the ``settings`` argument is passed, it should be a Python dictionary
adfc23 131     representing the :term:`deployment settings` for this application.  These
CM 132     are later retrievable using the
133     :attr:`pyramid.registry.Registry.settings` attribute (aka
134     ``request.registry.settings``).
5bf23f 135
CM 136     If the ``root_factory`` argument is passed, it should be an object
adfc23 137     representing the default :term:`root factory` for your application or a
CM 138     :term:`dotted Python name` to the same.  If it is ``None``, a default
139     root factory will be used.
5bf23f 140
CM 141     If ``authentication_policy`` is passed, it should be an instance
142     of an :term:`authentication policy` or a :term:`dotted Python
adfc23 143     name` to the same.
5bf23f 144
CM 145     If ``authorization_policy`` is passed, it should be an instance of
146     an :term:`authorization policy` or a :term:`dotted Python name` to
adfc23 147     the same.
5bf23f 148
CM 149     .. note:: A ``ConfigurationError`` will be raised when an
150        authorization policy is supplied without also supplying an
151        authentication policy (authorization requires authentication).
152
3778e8 153     If ``renderers`` is ``None`` (the default), a default set of
TL 154     :term:`renderer` factories is used. Else, it should be a list of
155     tuples representing a set of renderer factories which should be
156     configured into this application, and each tuple representing a set of
5bf23f 157     positional values that should be passed to
3778e8 158     :meth:`pyramid.config.Configurator.add_renderer`.
5bf23f 159
CM 160     If ``debug_logger`` is not passed, a default debug logger that logs to a
161     logger will be used (the logger name will be the package name of the
162     *caller* of this configurator).  If it is passed, it should be an
163     instance of the :class:`logging.Logger` (PEP 282) standard library class
164     or a Python logger name.  The debug logger is used by :app:`Pyramid`
165     itself to log warnings and authorization debugging information.
166
167     If ``locale_negotiator`` is passed, it should be a :term:`locale
168     negotiator` implementation or a :term:`dotted Python name` to
169     same.  See :ref:`custom_locale_negotiator`.
170
171     If ``request_factory`` is passed, it should be a :term:`request
adfc23 172     factory` implementation or a :term:`dotted Python name` to the same.
5bf23f 173     See :ref:`changing_the_request_factory`.  By default it is ``None``,
CM 174     which means use the default request factory.
175
1236de 176     If ``response_factory`` is passed, it should be a :term:`response
JA 177     factory` implementation or a :term:`dotted Python name` to the same.
178     See :ref:`changing_the_response_factory`.  By default it is ``None``,
179     which means use the default response factory.
180
5bf23f 181     If ``default_permission`` is passed, it should be a
CM 182     :term:`permission` string to be used as the default permission for
183     all view configuration registrations performed against this
184     Configurator.  An example of a permission string:``'view'``.
185     Adding a default permission makes it unnecessary to protect each
186     view configuration with an explicit permission, unless your
187     application policy requires some exception for a particular view.
188     By default, ``default_permission`` is ``None``, meaning that view
189     configurations which do not explicitly declare a permission will
190     always be executable by entirely anonymous users (any
2033ee 191     authorization policy in effect is ignored).
1236de 192
2033ee 193     .. seealso::
SP 194
195         See also :ref:`setting_a_default_permission`.
5bf23f 196
CM 197     If ``session_factory`` is passed, it should be an object which
198     implements the :term:`session factory` interface.  If a nondefault
199     value is passed, the ``session_factory`` will be used to create a
200     session object when ``request.session`` is accessed.  Note that
201     the same outcome can be achieved by calling
202     :meth:`pyramid.config.Configurator.set_session_factory`.  By
203     default, this argument is ``None``, indicating that no session
204     factory will be configured (and thus accessing ``request.session``
205     will throw an error) unless ``set_session_factory`` is called later
206     during configuration.
207
208     If ``autocommit`` is ``True``, every method called on the configurator
209     will cause an immediate action, and no configuration conflict detection
210     will be used. If ``autocommit`` is ``False``, most methods of the
211     configurator will defer their action until
212     :meth:`pyramid.config.Configurator.commit` is called.  When
213     :meth:`pyramid.config.Configurator.commit` is called, the actions implied
214     by the called methods will be checked for configuration conflicts unless
5c351a 215     ``autocommit`` is ``True``.  If a conflict is detected, a
5bf23f 216     ``ConfigurationConflictError`` will be raised.  Calling
CM 217     :meth:`pyramid.config.Configurator.make_wsgi_app` always implies a final
218     commit.
219
220     If ``default_view_mapper`` is passed, it will be used as the default
221     :term:`view mapper` factory for view configurations that don't otherwise
a3f67c 222     specify one (see :class:`pyramid.interfaces.IViewMapperFactory`).  If
d0e652 223     ``default_view_mapper`` is not passed, a superdefault view mapper will be
5bf23f 224     used.
CM 225
226     If ``exceptionresponse_view`` is passed, it must be a :term:`view
227     callable` or ``None``.  If it is a view callable, it will be used as an
228     exception view callable when an :term:`exception response` is raised. If
229     ``exceptionresponse_view`` is ``None``, no exception response view will
230     be registered, and all raised exception responses will be bubbled up to
231     Pyramid's caller.  By
232     default, the ``pyramid.httpexceptions.default_exceptionresponse_view``
0b23b3 233     function is used as the ``exceptionresponse_view``.
5bf23f 234
CM 235     If ``route_prefix`` is passed, all routes added with
236     :meth:`pyramid.config.Configurator.add_route` will have the specified path
0b23b3 237     prepended to their pattern.
5bf23f 238
844ed9 239     If ``introspection`` is passed, it must be a boolean value.  If it's
043ccd 240     ``True``, introspection values during actions will be kept for use
844ed9 241     for tools like the debug toolbar.  If it's ``False``, introspection
CM 242     values provided by registrations will be ignored.  By default, it is
0b23b3 243     ``True``.
TL 244
245     .. versionadded:: 1.1
246        The ``exceptionresponse_view`` argument.
247
248     .. versionadded:: 1.2
249        The ``route_prefix`` argument.
250
251     .. versionadded:: 1.3
252        The ``introspection`` argument.
ae6c88 253
MM 254     .. versionadded:: 1.6
255        The ``root_package`` argument.
1236de 256        The ``response_factory`` argument.
134ef7 257
MM 258     .. versionadded:: 1.9
259        The ability to use the configurator as a context manager with the
260        ``with``-statement to make threadlocal configuration available for
261        further configuration with an implicit commit.
e49638 262     """
0c29cf 263
MM 264     manager = manager  # for testing injection
265     venusian = venusian  # for testing injection
5bf23f 266     _ainfo = None
b86fa9 267     basepath = None
CM 268     includepath = ()
269     info = ''
8b6f09 270     object_description = staticmethod(object_description)
e49638 271     introspectable = Introspectable
5ad401 272     inspect = inspect
5bf23f 273
0c29cf 274     def __init__(
MM 275         self,
276         registry=None,
277         package=None,
278         settings=None,
279         root_factory=None,
280         authentication_policy=None,
281         authorization_policy=None,
282         renderers=None,
283         debug_logger=None,
284         locale_negotiator=None,
285         request_factory=None,
286         response_factory=None,
287         default_permission=None,
288         session_factory=None,
289         default_view_mapper=None,
290         autocommit=False,
291         exceptionresponse_view=default_exceptionresponse_view,
292         route_prefix=None,
293         introspection=True,
294         root_package=None,
295     ):
5bf23f 296         if package is None:
CM 297             package = caller_package()
ae6c88 298         if root_package is None:
MM 299             root_package = package
5bf23f 300         name_resolver = DottedNameResolver(package)
CM 301         self.name_resolver = name_resolver
078859 302         self.package_name = name_resolver.get_package_name()
CM 303         self.package = name_resolver.get_package()
ae6c88 304         self.root_package = root_package
5bf23f 305         self.registry = registry
CM 306         self.autocommit = autocommit
307         self.route_prefix = route_prefix
844ed9 308         self.introspection = introspection
5bf23f 309         if registry is None:
CM 310             registry = Registry(self.package_name)
311             self.registry = registry
312             self.setup_registry(
313                 settings=settings,
314                 root_factory=root_factory,
315                 authentication_policy=authentication_policy,
316                 authorization_policy=authorization_policy,
317                 renderers=renderers,
318                 debug_logger=debug_logger,
319                 locale_negotiator=locale_negotiator,
320                 request_factory=request_factory,
1236de 321                 response_factory=response_factory,
5bf23f 322                 default_permission=default_permission,
CM 323                 session_factory=session_factory,
324                 default_view_mapper=default_view_mapper,
325                 exceptionresponse_view=exceptionresponse_view,
0c29cf 326             )
5bf23f 327
0c29cf 328     def setup_registry(
MM 329         self,
330         settings=None,
331         root_factory=None,
332         authentication_policy=None,
333         authorization_policy=None,
334         renderers=None,
335         debug_logger=None,
336         locale_negotiator=None,
337         request_factory=None,
338         response_factory=None,
339         default_permission=None,
340         session_factory=None,
341         default_view_mapper=None,
342         exceptionresponse_view=default_exceptionresponse_view,
343     ):
5bf23f 344         """ When you pass a non-``None`` ``registry`` argument to the
adfc23 345         :term:`Configurator` constructor, no initial setup is performed
5bf23f 346         against the registry.  This is because the registry you pass in may
CM 347         have already been initialized for use under :app:`Pyramid` via a
348         different configurator.  However, in some circumstances (such as when
adfc23 349         you want to use a global registry instead of a registry created as a
CM 350         result of the Configurator constructor), or when you want to reset
351         the initial setup of a registry, you *do* want to explicitly
352         initialize the registry associated with a Configurator for use under
353         :app:`Pyramid`.  Use ``setup_registry`` to do this initialization.
5bf23f 354
CM 355         ``setup_registry`` configures settings, a root factory, security
356         policies, renderers, a debug logger, a locale negotiator, and various
357         other settings using the configurator's current registry, as per the
358         descriptions in the Configurator constructor."""
c1624c 359
5bf23f 360         registry = self.registry
c1624c 361
5bf23f 362         self._fix_registry()
e49638 363
5bf23f 364         self._set_settings(settings)
CM 365
e6c2d2 366         if isinstance(debug_logger, string_types):
c1624c 367             debug_logger = logging.getLogger(debug_logger)
CM 368
5bf23f 369         if debug_logger is None:
CM 370             debug_logger = logging.getLogger(self.package_name)
012b97 371
5bf23f 372         registry.registerUtility(debug_logger, IDebugLogger)
CM 373
27190e 374         self.add_default_response_adapters()
b7e92d 375         self.add_default_renderers()
121f45 376         self.add_default_accept_view_order()
a00621 377         self.add_default_view_predicates()
ceb1f2 378         self.add_default_view_derivers()
9c8ec5 379         self.add_default_route_predicates()
35b0e3 380         self.add_default_tweens()
7c0f09 381         self.add_default_security()
a00621 382
5bf23f 383         if exceptionresponse_view is not None:
CM 384             exceptionresponse_view = self.maybe_dotted(exceptionresponse_view)
385             self.add_view(exceptionresponse_view, context=IExceptionResponse)
0c29cf 386             self.add_view(
MM 387                 exceptionresponse_view, context=WebobWSGIHTTPException
388             )
5bf23f 389
0ded4e 390         # commit below because:
CM 391         #
392         # - the default exceptionresponse_view requires the superdefault view
a54bc1 393         #   mapper, so we need to configure it before adding
MM 394         #   default_view_mapper
0ded4e 395         #
257f2c 396         # - superdefault renderers should be overrideable without requiring
0ded4e 397         #   the user to commit before calling config.add_renderer
ea824f 398
CM 399         self.commit()
400
27190e 401         # self.commit() should not be called within this method after this
CM 402         # point because the following registrations should be treated as
403         # analogues of methods called by the user after configurator
404         # construction.  Rationale: user-supplied implementations should be
405         # preferred rather than add-on author implementations with the help of
406         # automatic conflict resolution.
ea824f 407
66da9b 408         if authentication_policy and not authorization_policy:
0c29cf 409             authorization_policy = ACLAuthorizationPolicy()  # default
66da9b 410
ea824f 411         if authorization_policy:
CM 412             self.set_authorization_policy(authorization_policy)
637bda 413
eb2fee 414         if authentication_policy:
CM 415             self.set_authentication_policy(authentication_policy)
416
417         if default_view_mapper is not None:
418             self.set_view_mapper(default_view_mapper)
f67ba4 419
637bda 420         if renderers:
CM 421             for name, renderer in renderers:
422                 self.add_renderer(name, renderer)
cfbbd6 423
2a818a 424         if root_factory is not None:
CM 425             self.set_root_factory(root_factory)
ea824f 426
5bf23f 427         if locale_negotiator:
ea824f 428             self.set_locale_negotiator(locale_negotiator)
5bf23f 429
CM 430         if request_factory:
431             self.set_request_factory(request_factory)
432
1236de 433         if response_factory:
JA 434             self.set_response_factory(response_factory)
435
5bf23f 436         if default_permission:
CM 437             self.set_default_permission(default_permission)
438
439         if session_factory is not None:
440             self.set_session_factory(session_factory)
441
25c64c 442         tweens = aslist(registry.settings.get('pyramid.tweens', []))
5bf23f 443         for factory in tweens:
CM 444             self._add_tween(factory, explicit=True)
012b97 445
ea824f 446         includes = aslist(registry.settings.get('pyramid.includes', []))
CM 447         for inc in includes:
448             self.include(inc)
449
5bf23f 450     def _make_spec(self, path_or_spec):
79ef3d 451         package, filename = resolve_asset_spec(path_or_spec, self.package_name)
5bf23f 452         if package is None:
0c29cf 453             return filename  # absolute filename
5bf23f 454         return '%s:%s' % (package, filename)
CM 455
456     def _fix_registry(self):
457         """ Fix up a ZCA component registry that is not a
458         pyramid.registry.Registry by adding analogues of ``has_listeners``,
459         ``notify``, ``queryAdapterOrSelf``, and ``registerSelfAdapter``
460         through monkey-patching."""
461
462         _registry = self.registry
463
464         if not hasattr(_registry, 'notify'):
0c29cf 465
5bf23f 466             def notify(*events):
0c29cf 467                 [_ for _ in _registry.subscribers(events, None)]
MM 468
5bf23f 469             _registry.notify = notify
CM 470
471         if not hasattr(_registry, 'has_listeners'):
472             _registry.has_listeners = True
473
474         if not hasattr(_registry, 'queryAdapterOrSelf'):
0c29cf 475
5bf23f 476             def queryAdapterOrSelf(object, interface, default=None):
CM 477                 if not interface.providedBy(object):
0c29cf 478                     return _registry.queryAdapter(
MM 479                         object, interface, default=default
480                     )
5bf23f 481                 return object
0c29cf 482
5bf23f 483             _registry.queryAdapterOrSelf = queryAdapterOrSelf
CM 484
485         if not hasattr(_registry, 'registerSelfAdapter'):
0c29cf 486
MM 487             def registerSelfAdapter(
488                 required=None,
489                 provided=None,
490                 name=empty,
491                 info=empty,
492                 event=True,
493             ):
494                 return _registry.registerAdapter(
495                     lambda x: x,
496                     required=required,
497                     provided=provided,
498                     name=name,
499                     info=info,
500                     event=event,
501                 )
502
5bf23f 503             _registry.registerSelfAdapter = registerSelfAdapter
CM 504
c15cbc 505         if not hasattr(_registry, '_lock'):
CM 506             _registry._lock = threading.Lock()
507
508         if not hasattr(_registry, '_clear_view_lookup_cache'):
0c29cf 509
c15cbc 510             def _clear_view_lookup_cache():
CM 511                 _registry._view_lookup_cache = {}
512
0c29cf 513             _registry._clear_view_lookup_cache = _clear_view_lookup_cache
c15cbc 514
5bf23f 515     # API
1236de 516
e49638 517     def _get_introspector(self):
CM 518         introspector = getattr(self.registry, 'introspector', _marker)
519         if introspector is _marker:
520             introspector = Introspector()
521             self._set_introspector(introspector)
522         return introspector
523
524     def _set_introspector(self, introspector):
525         self.registry.introspector = introspector
526
527     def _del_introspector(self):
528         del self.registry.introspector
529
078859 530     introspector = property(
CM 531         _get_introspector, _set_introspector, _del_introspector
0c29cf 532     )
5bf23f 533
405213 534     def get_predlist(self, name):
95f766 535         predlist = self.registry.queryUtility(IPredicateList, name=name)
CM 536         if predlist is None:
537             predlist = PredicateList()
538             self.registry.registerUtility(predlist, IPredicateList, name=name)
539         return predlist
540
0c29cf 541     def _add_predicate(
MM 542         self, type, name, factory, weighs_more_than=None, weighs_less_than=None
543     ):
06b839 544         factory = self.maybe_dotted(factory)
c2c589 545         discriminator = ('%s option' % type, name)
95f766 546         intr = self.introspectable(
CM 547             '%s predicates' % type,
548             discriminator,
549             '%s predicate named %s' % (type, name),
0c29cf 550             '%s predicate' % type,
MM 551         )
95f766 552         intr['name'] = name
06b839 553         intr['factory'] = factory
95f766 554         intr['weighs_more_than'] = weighs_more_than
CM 555         intr['weighs_less_than'] = weighs_less_than
0c29cf 556
95f766 557         def register():
405213 558             predlist = self.get_predlist(type)
0c29cf 559             predlist.add(
MM 560                 name,
561                 factory,
562                 weighs_more_than=weighs_more_than,
563                 weighs_less_than=weighs_less_than,
564             )
565
566         self.action(
567             discriminator,
568             register,
569             introspectables=(intr,),
570             order=PHASE1_CONFIG,
571         )  # must be registered early
95f766 572
5bf23f 573     def include(self, callable, route_prefix=None):
f7c173 574         """Include a configuration callable, to support imperative
5bf23f 575         application extensibility.
CM 576
577         .. warning:: In versions of :app:`Pyramid` prior to 1.2, this
578             function accepted ``*callables``, but this has been changed
579             to support only a single callable.
580
581         A configuration callable should be a callable that accepts a single
582         argument named ``config``, which will be an instance of a
2e95ac 583         :term:`Configurator`.  However, be warned that it will not be the same
TL 584         configurator instance on which you call this method.  The
e09e08 585         code which runs as a result of calling the callable should invoke
5bf23f 586         methods on the configurator passed to it which add configuration
CM 587         state.  The return value of a callable will be ignored.
588
589         Values allowed to be presented via the ``callable`` argument to
590         this method: any callable Python object or any :term:`dotted Python
591         name` which resolves to a callable Python object.  It may also be a
592         Python :term:`module`, in which case, the module will be searched for
593         a callable named ``includeme``, which will be treated as the
594         configuration callable.
b86fa9 595
5bf23f 596         For example, if the ``includeme`` function below lives in a module
CM 597         named ``myapp.myconfig``:
598
599         .. code-block:: python
600            :linenos:
601
602            # myapp.myconfig module
603
604            def my_view(request):
605                from pyramid.response import Response
606                return Response('OK')
607
608            def includeme(config):
609                config.add_view(my_view)
610
026ac8 611         You might cause it to be included within your Pyramid application like
5bf23f 612         so:
CM 613
614         .. code-block:: python
615            :linenos:
616
617            from pyramid.config import Configurator
618
619            def main(global_config, **settings):
620                config = Configurator()
621                config.include('myapp.myconfig.includeme')
622
623         Because the function is named ``includeme``, the function name can
624         also be omitted from the dotted name reference:
625
626         .. code-block:: python
627            :linenos:
628
629            from pyramid.config import Configurator
630
631            def main(global_config, **settings):
632                config = Configurator()
633                config.include('myapp.myconfig')
634
635         Included configuration statements will be overridden by local
636         configuration statements if an included callable causes a
637         configuration conflict by registering something with the same
638         configuration parameters.
639
640         If the ``route_prefix`` is supplied, it must be a string.  Any calls
641         to :meth:`pyramid.config.Configurator.add_route` within the included
642         callable will have their pattern prefixed with the value of
643         ``route_prefix``. This can be used to help mount a set of routes at a
2e95ac 644         different location than the included callable's author intended, while
5bf23f 645         still maintaining the same route names.  For example:
012b97 646
5bf23f 647         .. code-block:: python
CM 648            :linenos:
649
650            from pyramid.config import Configurator
651
652            def included(config):
653                config.add_route('show_users', '/show')
012b97 654
5bf23f 655            def main(global_config, **settings):
CM 656                config = Configurator()
657                config.include(included, route_prefix='/users')
658
659         In the above configuration, the ``show_users`` route will have an
660         effective route pattern of ``/users/show``, instead of ``/show``
661         because the ``route_prefix`` argument will be prepended to the
662         pattern.
663
0b23b3 664         .. versionadded:: 1.2
TL 665            The ``route_prefix`` parameter.
666
f5ff7e 667         .. versionchanged:: 1.9
MM 668            The included function is wrapped with a call to
669            :meth:`pyramid.config.Configurator.begin` and
670            :meth:`pyramid.config.Configurator.end` while it is executed.
671
5bf23f 672         """
7a7c8c 673         # """ <-- emacs
5bf23f 674
b86fa9 675         action_state = self.action_state
5bf23f 676
CM 677         c = self.maybe_dotted(callable)
5ad401 678         module = self.inspect.getmodule(c)
5bf23f 679         if module is c:
f8bfc6 680             try:
CM 681                 c = getattr(module, 'includeme')
682             except AttributeError:
683                 raise ConfigurationError(
0c29cf 684                     "module %r has no attribute 'includeme'"
MM 685                     % (module.__name__)
686                 )
687
5bf23f 688         spec = module.__name__ + ':' + c.__name__
5ad401 689         sourcefile = self.inspect.getsourcefile(c)
CM 690
691         if sourcefile is None:
692             raise ConfigurationError(
693                 'No source file for module %r (.py file must exist, '
0c29cf 694                 'refusing to use orphan .pyc or .pyo file).' % module.__name__
MM 695             )
5bf23f 696
b86fa9 697         if action_state.processSpec(spec):
efd61e 698             with self.route_prefix_context(route_prefix):
HS 699                 configurator = self.__class__(
700                     registry=self.registry,
701                     package=package_of(module),
702                     root_package=self.root_package,
703                     autocommit=self.autocommit,
704                     route_prefix=self.route_prefix,
0c29cf 705                 )
efd61e 706                 configurator.basepath = os.path.dirname(sourcefile)
HS 707                 configurator.includepath = self.includepath + (spec,)
708
709                 self.begin()
710                 try:
711                     c(configurator)
712                 finally:
713                     self.end()
012b97 714
5bf23f 715     def add_directive(self, name, directive, action_wrap=True):
CM 716         """
717         Add a directive method to the configurator.
718
719         .. warning:: This method is typically only used by :app:`Pyramid`
720            framework extension authors, not by :app:`Pyramid` application
721            developers.
722
723         Framework extenders can add directive methods to a configurator by
724         instructing their users to call ``config.add_directive('somename',
725         'some.callable')``.  This will make ``some.callable`` accessible as
726         ``config.somename``.  ``some.callable`` should be a function which
727         accepts ``config`` as a first argument, and arbitrary positional and
728         keyword arguments following.  It should use config.action as
729         necessary to perform actions.  Directive methods can then be invoked
730         like 'built-in' directives such as ``add_view``, ``add_route``, etc.
731
732         The ``action_wrap`` argument should be ``True`` for directives which
733         perform ``config.action`` with potentially conflicting
734         discriminators.  ``action_wrap`` will cause the directive to be
735         wrapped in a decorator which provides more accurate conflict
736         cause information.
012b97 737
5bf23f 738         ``add_directive`` does not participate in conflict detection, and
CM 739         later calls to ``add_directive`` will override earlier calls.
740         """
741         c = self.maybe_dotted(directive)
742         if not hasattr(self.registry, '_directives'):
743             self.registry._directives = {}
744         self.registry._directives[name] = (c, action_wrap)
745
746     def __getattr__(self, name):
747         # allow directive extension names to work
748         directives = getattr(self.registry, '_directives', {})
749         c = directives.get(name)
750         if c is None:
751             raise AttributeError(name)
752         c, action_wrap = c
753         if action_wrap:
754             c = action_method(c)
c7cc88 755         # Create a bound method (works on both Py2 and Py3)
CM 756         # http://stackoverflow.com/a/1015405/209039
757         m = c.__get__(self, self.__class__)
5bf23f 758         return m
CM 759
760     def with_package(self, package):
761         """ Return a new Configurator instance with the same registry
80281d 762         as this configurator. ``package`` may be an actual Python package
TL 763         object or a :term:`dotted Python name` representing a package."""
b86fa9 764         configurator = self.__class__(
CM 765             registry=self.registry,
766             package=package,
ae6c88 767             root_package=self.root_package,
b86fa9 768             autocommit=self.autocommit,
CM 769             route_prefix=self.route_prefix,
844ed9 770             introspection=self.introspection,
0c29cf 771         )
b86fa9 772         configurator.basepath = self.basepath
CM 773         configurator.includepath = self.includepath
774         configurator.info = self.info
775         return configurator
5bf23f 776
CM 777     def maybe_dotted(self, dotted):
778         """ Resolve the :term:`dotted Python name` ``dotted`` to a
779         global Python object.  If ``dotted`` is not a string, return
780         it without attempting to do any name resolution.  If
781         ``dotted`` is a relative dotted name (e.g. ``.foo.bar``,
782         consider it relative to the ``package`` argument supplied to
783         this Configurator's constructor."""
784         return self.name_resolver.maybe_resolve(dotted)
785
786     def absolute_asset_spec(self, relative_spec):
787         """ Resolve the potentially relative :term:`asset
788         specification` string passed as ``relative_spec`` into an
789         absolute asset specification string and return the string.
790         Use the ``package`` of this configurator as the package to
791         which the asset specification will be considered relative
792         when generating an absolute asset specification.  If the
793         provided ``relative_spec`` argument is already absolute, or if
794         the ``relative_spec`` is not a string, it is simply returned."""
e6c2d2 795         if not isinstance(relative_spec, string_types):
5bf23f 796             return relative_spec
CM 797         return self._make_spec(relative_spec)
798
0c29cf 799     absolute_resource_spec = absolute_asset_spec  # b/w compat forever
5bf23f 800
804eb0 801     def begin(self, request=_marker):
5bf23f 802         """ Indicate that application or test configuration has begun.
CM 803         This pushes a dictionary containing the :term:`application
804         registry` implied by ``registry`` attribute of this
805         configurator and the :term:`request` implied by the
f271a6 806         ``request`` argument onto the :term:`thread local` stack
5bf23f 807         consulted by various :mod:`pyramid.threadlocal` API
804eb0 808         functions.
MM 809
810         If ``request`` is not specified and the registry owned by the
811         configurator is already pushed as the current threadlocal registry
812         then this method will keep the current threadlocal request unchanged.
813
814         .. versionchanged:: 1.8
815            The current threadlocal request is propagated if the current
816            threadlocal registry remains unchanged.
817
818         """
819         if request is _marker:
820             current = self.manager.get()
821             if current['registry'] == self.registry:
822                 request = current['request']
823             else:
824                 request = None
0c29cf 825         self.manager.push({'registry': self.registry, 'request': request})
5bf23f 826
CM 827     def end(self):
828         """ Indicate that application or test configuration has ended.
f271a6 829         This pops the last value pushed onto the :term:`thread local`
5bf23f 830         stack (usually by the ``begin`` method) and returns that
CM 831         value.
832         """
833         return self.manager.pop()
834
134ef7 835     def __enter__(self):
MM 836         self.begin()
837         return self
838
839     def __exit__(self, exc_type, exc_value, exc_traceback):
840         self.end()
841
842         if exc_value is None:
843             self.commit()
844
5bf23f 845     # this is *not* an action method (uses caller_package)
0c29cf 846     def scan(
MM 847         self, package=None, categories=None, onerror=None, ignore=None, **kw
848     ):
5bf23f 849         """Scan a Python package and any of its subpackages for objects
CM 850         marked with :term:`configuration decoration` such as
851         :class:`pyramid.view.view_config`.  Any decorated object found will
852         influence the current configuration state.
853
854         The ``package`` argument should be a Python :term:`package` or module
855         object (or a :term:`dotted Python name` which refers to such a
856         package or module).  If ``package`` is ``None``, the package of the
857         *caller* is used.
858
859         The ``categories`` argument, if provided, should be the
860         :term:`Venusian` 'scan categories' to use during scanning.  Providing
861         this argument is not often necessary; specifying scan categories is
862         an extremely advanced usage.  By default, ``categories`` is ``None``
863         which will execute *all* Venusian decorator callbacks including
864         :app:`Pyramid`-related decorators such as
865         :class:`pyramid.view.view_config`.  See the :term:`Venusian`
866         documentation for more information about limiting a scan by using an
867         explicit set of categories.
868
1aeae3 869         The ``onerror`` argument, if provided, should be a Venusian
CM 870         ``onerror`` callback function.  The onerror function is passed to
871         :meth:`venusian.Scanner.scan` to influence error behavior when an
872         exception is raised during the scanning process.  See the
873         :term:`Venusian` documentation for more information about ``onerror``
874         callbacks.
875
e4b8fa 876         The ``ignore`` argument, if provided, should be a Venusian ``ignore``
CM 877         value.  Providing an ``ignore`` argument allows the scan to ignore
878         particular modules, packages, or global objects during a scan.
879         ``ignore`` can be a string or a callable, or a list containing
880         strings or callables.  The simplest usage of ``ignore`` is to provide
881         a module or package by providing a full path to its dotted name.  For
882         example: ``config.scan(ignore='my.module.subpackage')`` would ignore
883         the ``my.module.subpackage`` package during a scan, which would
884         prevent the subpackage and any of its submodules from being imported
885         and scanned.  See the :term:`Venusian` documentation for more
886         information about the ``ignore`` argument.
887
5bf23f 888         To perform a ``scan``, Pyramid creates a Venusian ``Scanner`` object.
CM 889         The ``kw`` argument represents a set of keyword arguments to pass to
890         the Venusian ``Scanner`` object's constructor.  See the
891         :term:`venusian` documentation (its ``Scanner`` class) for more
892         information about the constructor.  By default, the only keyword
893         arguments passed to the Scanner constructor are ``{'config':self}``
894         where ``self`` is this configurator object.  This services the
895         requirement of all built-in Pyramid decorators, but extension systems
896         may require additional arguments.  Providing this argument is not
897         often necessary; it's an advanced usage.
898
0b23b3 899         .. versionadded:: 1.1
TL 900            The ``**kw`` argument.
901
902         .. versionadded:: 1.3
903            The ``ignore`` argument.
904
5bf23f 905         """
CM 906         package = self.maybe_dotted(package)
0c29cf 907         if package is None:  # pragma: no cover
5bf23f 908             package = caller_package()
CM 909
25c64c 910         ctorkw = {'config': self}
1aeae3 911         ctorkw.update(kw)
5bf23f 912
1aeae3 913         scanner = self.venusian.Scanner(**ctorkw)
25c64c 914
0c29cf 915         scanner.scan(
MM 916             package, categories=categories, onerror=onerror, ignore=ignore
917         )
5bf23f 918
CM 919     def make_wsgi_app(self):
920         """ Commits any pending configuration statements, sends a
921         :class:`pyramid.events.ApplicationCreated` event to all listeners,
922         adds this configuration's registry to
923         :attr:`pyramid.config.global_registries`, and returns a
924         :app:`Pyramid` WSGI application representing the committed
925         configuration state."""
926         self.commit()
927         app = Router(self.registry)
cfbbd6 928
cfb2b5 929         # Allow tools like "pshell development.ini" to find the 'last'
cfbbd6 930         # registry configured.
5bf23f 931         global_registries.add(self.registry)
cfbbd6 932
f271a6 933         # Push the registry onto the stack in case any code that depends on
cfbbd6 934         # the registry threadlocal APIs used in listeners subscribed to the
CM 935         # IApplicationCreated event.
0c1c58 936         self.begin()
5bf23f 937         try:
CM 938             self.registry.notify(ApplicationCreated(app))
939         finally:
0c1c58 940             self.end()
5bf23f 941
CM 942         return app
79ef3d 943
0f9a56 944
5bf23f 945 global_registries = WeakOrderedSet()