{
    "file_diffs": [
        {
            "old_file_content": ".. _viewderivers_module:\n\n:mod:`pyramid.viewderivers`\n---------------------------\n\n.. automodule:: pyramid.viewderivers\n\n   .. attribute:: INGRESS\n\n      Constant representing the request ingress, for use in ``under``\n      arguments to :meth:`pyramid.config.Configurator.add_view_deriver`.\n\n   .. attribute:: MAPPED_VIEW\n\n      Constant representing the closest view deriver, for use in ``over``\n      arguments to :meth:`pyramid.config.Configurator.add_view_deriver`.\n",
            "new_file_content": ".. _viewderivers_module:\n\n:mod:`pyramid.viewderivers`\n---------------------------\n\n.. automodule:: pyramid.viewderivers\n\n   .. attribute:: INGRESS\n\n      Constant representing the request ingress, for use in ``under``\n      arguments to :meth:`pyramid.config.Configurator.add_view_deriver`.\n\n   .. attribute:: VIEW\n\n      Constant representing the :term:`view callable` at the end of the view\n      pipeline, for use in ``over`` arguments to\n      :meth:`pyramid.config.Configurator.add_view_deriver`.\n",
            "header": {
                "file": {
                    "path": "docs/api/viewderivers.rst"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "a4ec107b6",
                "new_commit_hash": "2a141501e",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/docs/api/viewderivers.rst"
            },
            "plus_file": {
                "path": "b/docs/api/viewderivers.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 10,
                            "length": 7
                        },
                        "new_range": {
                            "start": 10,
                            "length": 8
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "      Constant representing the request ingress, for use in ``under``",
                                "type": "context"
                            },
                            {
                                "content": "      arguments to :meth:`pyramid.config.Configurator.add_view_deriver`.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "   .. attribute:: MAPPED_VIEW",
                                "type": "deleted"
                            },
                            {
                                "content": "   .. attribute:: VIEW",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "      Constant representing the closest view deriver, for use in ``over``",
                                "type": "deleted"
                            },
                            {
                                "content": "      arguments to :meth:`pyramid.config.Configurator.add_view_deriver`.",
                                "type": "deleted"
                            },
                            {
                                "content": "      Constant representing the :term:`view callable` at the end of the view",
                                "type": "added"
                            },
                            {
                                "content": "      pipeline, for use in ``over`` arguments to",
                                "type": "added"
                            },
                            {
                                "content": "      :meth:`pyramid.config.Configurator.add_view_deriver`.",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": ".. _hooks_chapter:\n\nUsing Hooks\n===========\n\n\"Hooks\" can be used to influence the behavior of the :app:`Pyramid` framework\nin various ways.\n\n.. index::\n   single: not found view\n\n.. _changing_the_notfound_view:\n\nChanging the Not Found View\n---------------------------\n\nWhen :app:`Pyramid` can't map a URL to view code, it invokes a :term:`Not Found\nView`, which is a :term:`view callable`. The default Not Found View can be\noverridden through application configuration.\n\nIf your application uses :term:`imperative configuration`, you can replace the\nNot Found View by using the\n:meth:`pyramid.config.Configurator.add_notfound_view` method:\n\n.. code-block:: python\n   :linenos:\n\n   def notfound(request):\n       return Response('Not Found, dude', status='404 Not Found')\n\n   def main(globals, **settings):\n       config = Configurator()\n       config.add_notfound_view(notfound)\n\nThe :term:`Not Found View` callable is a view callable like any other.\n\nIf your application instead uses :class:`pyramid.view.view_config` decorators\nand a :term:`scan`, you can replace the Not Found View by using the\n:class:`pyramid.view.notfound_view_config` decorator:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import notfound_view_config\n\n   @notfound_view_config()\n   def notfound(request):\n       return Response('Not Found, dude', status='404 Not Found')\n\n   def main(globals, **settings):\n       config = Configurator()\n       config.scan()\n\nThis does exactly what the imperative example above showed.\n\nYour application can define *multiple* Not Found Views if necessary.  Both\n:meth:`pyramid.config.Configurator.add_notfound_view` and\n:class:`pyramid.view.notfound_view_config` take most of the same arguments as\n:class:`pyramid.config.Configurator.add_view` and\n:class:`pyramid.view.view_config`, respectively.  This means that Not Found\nViews can carry predicates limiting their applicability.  For example:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import notfound_view_config\n\n   @notfound_view_config(request_method='GET')\n   def notfound_get(request):\n       return Response('Not Found during GET, dude', status='404 Not Found')\n\n   @notfound_view_config(request_method='POST')\n   def notfound_post(request):\n       return Response('Not Found during POST, dude', status='404 Not Found')\n\n   def main(globals, **settings):\n      config = Configurator()\n      config.scan()\n\nThe ``notfound_get`` view will be called when a view could not be found and the\nrequest method was ``GET``.  The ``notfound_post`` view will be called when a\nview could not be found and the request method was ``POST``.\n\nLike any other view, the Not Found View must accept at least a ``request``\nparameter, or both ``context`` and ``request``.  The ``request`` is the current\n:term:`request` representing the denied action.  The ``context`` (if used in\nthe call signature) will be the instance of the\n:exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the view to\nbe called.\n\nBoth :meth:`pyramid.config.Configurator.add_notfound_view` and\n:class:`pyramid.view.notfound_view_config` can be used to automatically\nredirect requests to slash-appended routes. See\n:ref:`redirecting_to_slash_appended_routes` for examples.\n\nHere's some sample code that implements a minimal :term:`Not Found View`\ncallable:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.httpexceptions import HTTPNotFound\n\n   def notfound(request):\n       return HTTPNotFound()\n\n.. note::\n\n   When a Not Found View callable is invoked, it is passed a :term:`request`.\n   The ``exception`` attribute of the request will be an instance of the\n   :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the Not\n   Found View to be called.  The value of ``request.exception.message`` will be\n   a value explaining why the Not Found exception was raised.  This message has\n   different values depending on whether the ``pyramid.debug_notfound``\n   environment setting is true or false.\n\n.. note::\n\n   Both :meth:`pyramid.config.Configurator.add_notfound_view` and\n   :class:`pyramid.view.notfound_view_config` are new as of Pyramid 1.3.\n   Older Pyramid documentation instructed users to use ``add_view`` instead,\n   with a ``context`` of ``HTTPNotFound``.  This still works; the convenience\n   method and decorator are just wrappers around this functionality.\n\n.. warning::\n\n   When a Not Found View callable accepts an argument list as described in\n   :ref:`request_and_context_view_definitions`, the ``context`` passed as the\n   first argument to the view callable will be the\n   :exc:`~pyramid.httpexceptions.HTTPNotFound` exception instance.  If\n   available, the resource context will still be available as\n   ``request.context``.\n\n.. index::\n   single: forbidden view\n\n.. _changing_the_forbidden_view:\n\nChanging the Forbidden View\n---------------------------\n\nWhen :app:`Pyramid` can't authorize execution of a view based on the\n:term:`authorization policy` in use, it invokes a :term:`forbidden view`. The\ndefault forbidden response has a 403 status code and is very plain, but the\nview which generates it can be overridden as necessary.\n\nThe :term:`forbidden view` callable is a view callable like any other.  The\n:term:`view configuration` which causes it to be a \"forbidden\" view consists of\nusing the :meth:`pyramid.config.Configurator.add_forbidden_view` API or the\n:class:`pyramid.view.forbidden_view_config` decorator.\n\nFor example, you can add a forbidden view by using the\n:meth:`pyramid.config.Configurator.add_forbidden_view` method to register a\nforbidden view:\n\n.. code-block:: python\n   :linenos:\n\n   def forbidden(request):\n       return Response('forbidden')\n\n   def main(globals, **settings):\n       config = Configurator()\n       config.add_forbidden_view(forbidden_view)\n\nIf instead you prefer to use decorators and a :term:`scan`, you can use the\n:class:`pyramid.view.forbidden_view_config` decorator to mark a view callable\nas a forbidden view:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import forbidden_view_config\n\n   @forbidden_view_config()\n   def forbidden(request):\n       return Response('forbidden')\n\n   def main(globals, **settings):\n      config = Configurator()\n      config.scan()\n\nLike any other view, the forbidden view must accept at least a ``request``\nparameter, or both ``context`` and ``request``.  If a forbidden view callable\naccepts both ``context`` and ``request``, the HTTP Exception is passed as\ncontext. The ``context`` as found by the router when the view was denied (which\nyou normally would expect) is available as ``request.context``.  The\n``request`` is the  current :term:`request` representing the denied action.\n\nHere's some sample code that implements a minimal forbidden view:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import view_config\n   from pyramid.response import Response\n\n   def forbidden_view(request):\n       return Response('forbidden')\n\n.. note::\n\n   When a forbidden view callable is invoked, it is passed a :term:`request`.\n   The ``exception`` attribute of the request will be an instance of the\n   :exc:`~pyramid.httpexceptions.HTTPForbidden` exception that caused the\n   forbidden view to be called.  The value of ``request.exception.message``\n   will be a value explaining why the forbidden exception was raised, and\n   ``request.exception.result`` will be extended information about the\n   forbidden exception.  These messages have different values depending on\n   whether the ``pyramid.debug_authorization`` environment setting is true or\n   false.\n\n.. index::\n   single: request factory\n\n.. _changing_the_request_factory:\n\nChanging the Request Factory\n----------------------------\n\nWhenever :app:`Pyramid` handles a request from a :term:`WSGI` server, it\ncreates a :term:`request` object based on the WSGI environment it has been\npassed.  By default, an instance of the :class:`pyramid.request.Request` class\nis created to represent the request object.\n\nThe class (a.k.a., \"factory\") that :app:`Pyramid` uses to create a request\nobject instance can be changed by passing a ``request_factory`` argument to the\nconstructor of the :term:`configurator`.  This argument can be either a\ncallable or a :term:`dotted Python name` representing a callable.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.request import Request\n\n   class MyRequest(Request):\n       pass\n\n   config = Configurator(request_factory=MyRequest)\n\nIf you're doing imperative configuration, and you'd rather do it after you've\nalready constructed a :term:`configurator`, it can also be registered via the\n:meth:`pyramid.config.Configurator.set_request_factory` method:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n   from pyramid.request import Request\n\n   class MyRequest(Request):\n       pass\n\n   config = Configurator()\n   config.set_request_factory(MyRequest)\n\n.. index::\n   single: request method\n\n.. _adding_request_method:\n\nAdding Methods or Properties to a Request Object\n------------------------------------------------\n\n.. versionadded:: 1.4\n\nSince each Pyramid application can only have one :term:`request` factory,\n:ref:`changing the request factory <changing_the_request_factory>` is not that\nextensible, especially if you want to build composable features (e.g., Pyramid\nadd-ons and plugins).\n\nA lazy property can be registered to the request object via the\n:meth:`pyramid.config.Configurator.add_request_method` API. This allows you to\nspecify a callable that will be available on the request object, but will not\nactually execute the function until accessed.\n\n.. warning::\n\n   This will silently override methods and properties from :term:`request\n   factory` that have the same name.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n\n   def total(request, *args):\n       return sum(args)\n\n   def prop(request):\n       print(\"getting the property\")\n       return \"the property\"\n\n   config = Configurator()\n   config.add_request_method(total)\n   config.add_request_method(prop, reify=True)\n\nIn the above example, ``total`` is added as a method. However, ``prop`` is\nadded as a property and its result is cached per-request by setting\n``reify=True``. This way, we eliminate the overhead of running the function\nmultiple times.\n\n   >>> request.total(1, 2, 3)\n   6\n   >>> request.prop\n   getting the property\n   the property\n   >>> request.prop\n   the property\n\nTo not cache the result of ``request.prop``, set ``property=True`` instead of\n``reify=True``.\n\nHere is an example of passing a class to ``Configurator.add_request_method``:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n   from pyramid.decorator import reify\n\n   class ExtraStuff(object):\n\n       def __init__(self, request):\n           self.request = request\n\n       def total(self, *args):\n           return sum(args)\n\n       # use @property if you don't want to cache the result\n       @reify\n       def prop(self):\n           print(\"getting the property\")\n           return \"the property\"\n\n   config = Configurator()\n   config.add_request_method(ExtraStuff, 'extra', reify=True)\n\nWe attach and cache an object named ``extra`` to the ``request`` object.\n\n   >>> request.extra.total(1, 2, 3)\n   6\n   >>> request.extra.prop\n   getting the property\n   the property\n   >>> request.extra.prop\n   the property\n\n.. index::\n   single: response factory\n\n.. _changing_the_response_factory:\n\nChanging the Response Factory\n-----------------------------\n\n.. versionadded:: 1.6\n\nWhenever :app:`Pyramid` returns a response from a view, it creates a\n:term:`response` object.  By default, an instance of the\n:class:`pyramid.response.Response` class is created to represent the response\nobject.\n\nThe factory that :app:`Pyramid` uses to create a response object instance can\nbe changed by passing a :class:`pyramid.interfaces.IResponseFactory` argument\nto the constructor of the :term:`configurator`.  This argument can be either a\ncallable or a :term:`dotted Python name` representing a callable.\n\nThe factory takes a single positional argument, which is a :term:`Request`\nobject. The argument may be ``None``.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n\n   class MyResponse(Response):\n       pass\n\n   config = Configurator(response_factory=lambda r: MyResponse())\n\nIf you're doing imperative configuration and you'd rather do it after you've\nalready constructed a :term:`configurator`, it can also be registered via the\n:meth:`pyramid.config.Configurator.set_response_factory` method:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n   from pyramid.response import Response\n\n   class MyResponse(Response):\n       pass\n\n   config = Configurator()\n   config.set_response_factory(lambda r: MyResponse())\n\n.. index::\n   single: before render event\n   single: adding renderer globals\n\n.. _beforerender_event:\n\nUsing the Before Render Event\n-----------------------------\n\nSubscribers to the :class:`pyramid.events.BeforeRender` event may introspect\nand modify the set of :term:`renderer globals` before they are passed to a\n:term:`renderer`.  This event object iself has a dictionary-like interface that\ncan be used for this purpose.  For example:\n\n.. code-block:: python\n    :linenos:\n\n    from pyramid.events import subscriber\n    from pyramid.events import BeforeRender\n\n    @subscriber(BeforeRender)\n    def add_global(event):\n        event['mykey'] = 'foo'\n\nAn object of this type is sent as an event just before a :term:`renderer` is\ninvoked.\n\nIf a subscriber attempts to add a key that already exists in the renderer\nglobals dictionary, a :exc:`KeyError` is raised.  This limitation is enforced\nbecause event subscribers do not possess any relative ordering.  The set of\nkeys added to the renderer globals dictionary by all\n:class:`pyramid.events.BeforeRender` subscribers and renderer globals factories\nmust be unique.\n\nThe dictionary returned from the view is accessible through the\n:attr:`rendering_val` attribute of a :class:`~pyramid.events.BeforeRender`\nevent.\n\nSuppose you return ``{'mykey': 'somevalue', 'mykey2': 'somevalue2'}`` from your\nview callable, like so:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import view_config\n\n   @view_config(renderer='some_renderer')\n   def myview(request):\n       return {'mykey': 'somevalue', 'mykey2': 'somevalue2'}\n\n:attr:`rendering_val` can be used to access these values from the\n:class:`~pyramid.events.BeforeRender` object:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.events import subscriber\n   from pyramid.events import BeforeRender\n\n   @subscriber(BeforeRender)\n   def read_return(event):\n       # {'mykey': 'somevalue'} is returned from the view\n       print(event.rendering_val['mykey'])\n\nSee the API documentation for the :class:`~pyramid.events.BeforeRender` event\ninterface at :class:`pyramid.interfaces.IBeforeRender`.\n\n.. index::\n   single: response callback\n\n.. _using_response_callbacks:\n\nUsing Response Callbacks\n------------------------\n\nUnlike many other web frameworks, :app:`Pyramid` does not eagerly create a\nglobal response object.  Adding a :term:`response callback` allows an\napplication to register an action to be performed against whatever response\nobject is returned by a view, usually in order to mutate the response.\n\nThe :meth:`pyramid.request.Request.add_response_callback` method is used to\nregister a response callback.\n\nA response callback is a callable which accepts two positional parameters:\n``request`` and ``response``.  For example:\n\n.. code-block:: python\n   :linenos:\n\n   def cache_callback(request, response):\n       \"\"\"Set the cache_control max_age for the response\"\"\"\n       if request.exception is not None:\n           response.cache_control.max_age = 360\n   request.add_response_callback(cache_callback)\n\nNo response callback is called if an unhandled exception happens in application\ncode, or if the response object returned by a :term:`view callable` is invalid.\nResponse callbacks *are*, however, invoked when a :term:`exception view` is\nrendered successfully.  In such a case, the :attr:`request.exception` attribute\nof the request when it enters a response callback will be an exception object\ninstead of its default value of ``None``.\n\nResponse callbacks are called in the order they're added\n(first-to-most-recently-added).  All response callbacks are called *before* the\n:class:`~pyramid.events.NewResponse` event is sent.  Errors raised by response\ncallbacks are not handled specially.  They will be propagated to the caller of\nthe :app:`Pyramid` router application.\n\nA response callback has a lifetime of a *single* request.  If you want a\nresponse callback to happen as the result of *every* request, you must\nre-register the callback into every new request (perhaps within a subscriber of\na :class:`~pyramid.events.NewRequest` event).\n\n.. index::\n   single: finished callback\n\n.. _using_finished_callbacks:\n\nUsing Finished Callbacks\n------------------------\n\nA :term:`finished callback` is a function that will be called unconditionally\nby the :app:`Pyramid` :term:`router` at the very end of request processing. A\nfinished callback can be used to perform an action at the end of a request\nunconditionally.\n\nThe :meth:`pyramid.request.Request.add_finished_callback` method is used to\nregister a finished callback.\n\nA finished callback is a callable which accepts a single positional parameter:\n``request``.  For example:\n\n.. code-block:: python\n   :linenos:\n\n   import logging\n\n   log = logging.getLogger(__name__)\n\n   def log_callback(request):\n       \"\"\"Log information at the end of request\"\"\"\n       log.debug('Request is finished.')\n   request.add_finished_callback(log_callback)\n\nFinished callbacks are called in the order they're added\n(first-to-most-recently-added).  Finished callbacks (unlike a :term:`response\ncallback`) are *always* called, even if an exception happens in application\ncode that prevents a response from being generated.\n\nThe set of finished callbacks associated with a request are called *very late*\nin the processing of that request; they are essentially the very last thing\ncalled by the :term:`router` before a request \"ends\". They are called after\nresponse processing has already occurred in a top-level ``finally:`` block\nwithin the router request processing code.  As a result, mutations performed to\nthe ``request`` provided to a finished callback will have no meaningful effect,\nbecause response processing will have already occurred, and the request's scope\nwill expire almost immediately after all finished callbacks have been\nprocessed.\n\nErrors raised by finished callbacks are not handled specially.  They will be\npropagated to the caller of the :app:`Pyramid` router application.\n\nA finished callback has a lifetime of a *single* request.  If you want a\nfinished callback to happen as the result of *every* request, you must\nre-register the callback into every new request (perhaps within a subscriber of\na :class:`~pyramid.events.NewRequest` event).\n\n.. index::\n   single: traverser\n\n.. _changing_the_traverser:\n\nChanging the Traverser\n----------------------\n\nThe default :term:`traversal` algorithm that :app:`Pyramid` uses is explained\nin :ref:`traversal_algorithm`.  Though it is rarely necessary, this default\nalgorithm can be swapped out selectively for a different traversal pattern via\nconfiguration.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n   from myapp.traversal import Traverser\n   config = Configurator()\n   config.add_traverser(Traverser)\n\nIn the example above, ``myapp.traversal.Traverser`` is assumed to be a class\nthat implements the following interface:\n\n.. code-block:: python\n   :linenos:\n\n   class Traverser(object):\n       def __init__(self, root):\n           \"\"\" Accept the root object returned from the root factory \"\"\"\n\n       def __call__(self, request):\n           \"\"\" Return a dictionary with (at least) the keys ``root``,\n           ``context``, ``view_name``, ``subpath``, ``traversed``,\n           ``virtual_root``, and ``virtual_root_path``.  These values are\n           typically the result of a resource tree traversal.  ``root``\n           is the physical root object, ``context`` will be a resource\n           object, ``view_name`` will be the view name used (a Unicode\n           name), ``subpath`` will be a sequence of Unicode names that\n           followed the view name but were not traversed, ``traversed``\n           will be a sequence of Unicode names that were traversed\n           (including the virtual root path, if any) ``virtual_root``\n           will be a resource object representing the virtual root (or the\n           physical root if traversal was not performed), and\n           ``virtual_root_path`` will be a sequence representing the\n           virtual root path (a sequence of Unicode names) or None if\n           traversal was not performed.\n\n           Extra keys for special purpose functionality can be added as\n           necessary.\n\n           All values returned in the dictionary will be made available\n           as attributes of the ``request`` object.\n           \"\"\"\n\nMore than one traversal algorithm can be active at the same time.  For\ninstance, if your :term:`root factory` returns more than one type of object\nconditionally, you could claim that an alternative traverser adapter is \"for\"\nonly one particular class or interface.  When the root factory returned an\nobject that implemented that class or interface, a custom traverser would be\nused.  Otherwise the default traverser would be used.  For example:\n\n.. code-block:: python\n   :linenos:\n\n   from myapp.traversal import Traverser\n   from myapp.resources import MyRoot\n   from pyramid.config import Configurator\n   config = Configurator()\n   config.add_traverser(Traverser, MyRoot)\n\nIf the above stanza was added to a Pyramid ``__init__.py`` file's ``main``\nfunction, :app:`Pyramid` would use the ``myapp.traversal.Traverser`` only when\nthe application :term:`root factory` returned an instance of the\n``myapp.resources.MyRoot`` object.  Otherwise it would use the default\n:app:`Pyramid` traverser to do traversal.\n\n.. index::\n   single: URL generator\n\n.. _changing_resource_url:\n\nChanging How :meth:`pyramid.request.Request.resource_url` Generates a URL\n-------------------------------------------------------------------------\n\nWhen you add a traverser as described in :ref:`changing_the_traverser`, it's\noften convenient to continue to use the\n:meth:`pyramid.request.Request.resource_url` API.  However, since the way\ntraversal is done will have been modified, the URLs it generates by default may\nbe incorrect when used against resources derived from your custom traverser.\n\nIf you've added a traverser, you can change how\n:meth:`~pyramid.request.Request.resource_url` generates a URL for a specific\ntype of resource by adding a call to\n:meth:`pyramid.config.Configurator.add_resource_url_adapter`.\n\nFor example:\n\n.. code-block:: python\n   :linenos:\n\n   from myapp.traversal import ResourceURLAdapter\n   from myapp.resources import MyRoot\n\n   config.add_resource_url_adapter(ResourceURLAdapter, MyRoot)\n\nIn the above example, the ``myapp.traversal.ResourceURLAdapter`` class will be\nused to provide services to :meth:`~pyramid.request.Request.resource_url` any\ntime the :term:`resource` passed to ``resource_url`` is of the class\n``myapp.resources.MyRoot``.  The ``resource_iface`` argument ``MyRoot``\nrepresents the type of interface that must be possessed by the resource for\nthis resource url factory to be found.  If the ``resource_iface`` argument is\nomitted, this resource URL adapter will be used for *all* resources.\n\nThe API that must be implemented by a class that provides\n:class:`~pyramid.interfaces.IResourceURL` is as follows:\n\n.. code-block:: python\n  :linenos:\n\n  class MyResourceURL(object):\n      \"\"\" An adapter which provides the virtual and physical paths of a\n          resource\n      \"\"\"\n      def __init__(self, resource, request):\n          \"\"\" Accept the resource and request and set self.physical_path and\n          self.virtual_path \"\"\"\n          self.virtual_path =  some_function_of(resource, request)\n          self.physical_path =  some_other_function_of(resource, request)\n\nThe default context URL generator is available for perusal as the class\n:class:`pyramid.traversal.ResourceURL` in the `traversal module\n<https://github.com/Pylons/pyramid/blob/master/pyramid/traversal.py>`_ of the\n:term:`Pylons` GitHub Pyramid repository.\n\nSee :meth:`pyramid.config.Configurator.add_resource_url_adapter` for more\ninformation.\n\n.. index::\n   single: IResponse\n   single: special view responses\n\n.. _using_iresponse:\n\nChanging How Pyramid Treats View Responses\n------------------------------------------\n\n.. versionadded:: 1.1\n\nIt is possible to control how Pyramid treats the result of calling a view\ncallable on a per-type basis by using a hook involving\n:meth:`pyramid.config.Configurator.add_response_adapter` or the\n:class:`~pyramid.response.response_adapter` decorator.\n\nPyramid, in various places, adapts the result of calling a view callable to the\n:class:`~pyramid.interfaces.IResponse` interface to ensure that the object\nreturned by the view callable is a \"true\" response object.  The vast majority\nof time, the result of this adaptation is the result object itself, as view\ncallables written by \"civilians\" who read the narrative documentation contained\nin this manual will always return something that implements the\n:class:`~pyramid.interfaces.IResponse` interface.  Most typically, this will be\nan instance of the :class:`pyramid.response.Response` class or a subclass. If a\ncivilian returns a non-Response object from a view callable that isn't\nconfigured to use a :term:`renderer`, they will typically expect the router to\nraise an error.  However, you can hook Pyramid in such a way that users can\nreturn arbitrary values from a view callable by providing an adapter which\nconverts the arbitrary return value into something that implements\n:class:`~pyramid.interfaces.IResponse`.\n\nFor example, if you'd like to allow view callables to return bare string\nobjects (without requiring a :term:`renderer` to convert a string to a response\nobject), you can register an adapter which converts the string to a Response:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n\n   def string_response_adapter(s):\n       response = Response(s)\n       return response\n\n   # config is an instance of pyramid.config.Configurator\n\n   config.add_response_adapter(string_response_adapter, str)\n\nLikewise, if you want to be able to return a simplified kind of response object\nfrom view callables, you can use the IResponse hook to register an adapter to\nthe more complex IResponse interface:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n\n   class SimpleResponse(object):\n       def __init__(self, body):\n           self.body = body\n\n   def simple_response_adapter(simple_response):\n       response = Response(simple_response.body)\n       return response\n\n   # config is an instance of pyramid.config.Configurator\n\n   config.add_response_adapter(simple_response_adapter, SimpleResponse)\n\nIf you want to implement your own Response object instead of using the\n:class:`pyramid.response.Response` object in any capacity at all, you'll have\nto make sure that the object implements every attribute and method outlined in\n:class:`pyramid.interfaces.IResponse` and you'll have to ensure that it uses\n``zope.interface.implementer(IResponse)`` as a class decorator.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.interfaces import IResponse\n   from zope.interface import implementer\n\n   @implementer(IResponse)\n   class MyResponse(object):\n       # ... an implementation of every method and attribute\n       # documented in IResponse should follow ...\n\nWhen an alternate response object implementation is returned by a view\ncallable, if that object asserts that it implements\n:class:`~pyramid.interfaces.IResponse` (via\n``zope.interface.implementer(IResponse)``) , an adapter needn't be registered\nfor the object; Pyramid will use it directly.\n\nAn IResponse adapter for ``webob.Response`` (as opposed to\n:class:`pyramid.response.Response`) is registered by Pyramid by default at\nstartup time, as by their nature, instances of this class (and instances of\nsubclasses of the class) will natively provide IResponse.  The adapter\nregistered for ``webob.Response`` simply returns the response object.\n\nInstead of using :meth:`pyramid.config.Configurator.add_response_adapter`, you\ncan use the :class:`pyramid.response.response_adapter` decorator:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n   from pyramid.response import response_adapter\n\n   @response_adapter(str)\n   def string_response_adapter(s):\n       response = Response(s)\n       return response\n\nThe above example, when scanned, has the same effect as:\n\n.. code-block:: python\n\n   config.add_response_adapter(string_response_adapter, str)\n\nThe :class:`~pyramid.response.response_adapter` decorator will have no effect\nuntil activated by a :term:`scan`.\n\n.. index::\n   single: view mapper\n\n.. _using_a_view_mapper:\n\nUsing a View Mapper\n-------------------\n\nThe default calling conventions for view callables are documented in the\n:ref:`views_chapter` chapter.  You can change the way users define view\ncallables by employing a :term:`view mapper`.\n\nA view mapper is an object that accepts a set of keyword arguments and which\nreturns a callable.  The returned callable is called with the :term:`view\ncallable` object.  The returned callable should itself return another callable\nwhich can be called with the \"internal calling protocol\" ``(context,\nrequest)``.\n\nYou can use a view mapper in a number of ways:\n\n- by setting a ``__view_mapper__`` attribute (which is the view mapper object)\n  on the view callable itself\n\n- by passing the mapper object to :meth:`pyramid.config.Configurator.add_view`\n  (or its declarative and decorator equivalents) as the ``mapper`` argument\n\n- by registering a *default* view mapper\n\nHere's an example of a view mapper that emulates (somewhat) a Pylons\n\"controller\".  The mapper is initialized with some keyword arguments.  Its\n``__call__`` method accepts the view object (which will be a class).  It uses\nthe ``attr`` keyword argument it is passed to determine which attribute should\nbe used as an action method.  The wrapper method it returns accepts ``(context,\nrequest)`` and returns the result of calling the action method with keyword\narguments implied by the :term:`matchdict` after popping the ``action`` out of\nit.  This somewhat emulates the Pylons style of calling action methods with\nrouting parameters pulled out of the route matching dict as keyword arguments.\n\n.. code-block:: python\n   :linenos:\n\n   # framework\n\n   class PylonsControllerViewMapper(object):\n       def __init__(self, **kw):\n           self.kw = kw\n\n       def __call__(self, view):\n           attr = self.kw['attr']\n           def wrapper(context, request):\n               matchdict = request.matchdict.copy()\n               matchdict.pop('action', None)\n               inst = view(request)\n               meth = getattr(inst, attr)\n               return meth(**matchdict)\n           return wrapper\n\n   class BaseController(object):\n       __view_mapper__ = PylonsControllerViewMapper\n\nA user might make use of these framework components like so:\n\n.. code-block:: python\n   :linenos:\n\n   # user application\n\n   from pyramid.response import Response\n   from pyramid.config import Configurator\n   import pyramid_handlers\n   from wsgiref.simple_server import make_server\n\n   class MyController(BaseController):\n       def index(self, id):\n           return Response(id)\n\n   if __name__ == '__main__':\n       config = Configurator()\n       config.include(pyramid_handlers)\n       config.add_handler('one', '/{id}', MyController, action='index')\n       config.add_handler('two', '/{action}/{id}', MyController)\n       server.make_server('0.0.0.0', 8080, config.make_wsgi_app())\n       server.serve_forever()\n\nThe :meth:`pyramid.config.Configurator.set_view_mapper` method can be used to\nset a *default* view mapper (overriding the superdefault view mapper used by\nPyramid itself).\n\nA *single* view registration can use a view mapper by passing the mapper as the\n``mapper`` argument to :meth:`~pyramid.config.Configurator.add_view`.\n\n.. index::\n   single: configuration decorator\n\n.. _registering_configuration_decorators:\n\nRegistering Configuration Decorators\n------------------------------------\n\nDecorators such as :class:`~pyramid.view.view_config` don't change the behavior\nof the functions or classes they're decorating.  Instead when a :term:`scan` is\nperformed, a modified version of the function or class is registered with\n:app:`Pyramid`.\n\nYou may wish to have your own decorators that offer such behaviour. This is\npossible by using the :term:`Venusian` package in the same way that it is used\nby :app:`Pyramid`.\n\nBy way of example, let's suppose you want to write a decorator that registers\nthe function it wraps with a :term:`Zope Component Architecture` \"utility\"\nwithin the :term:`application registry` provided by :app:`Pyramid`. The\napplication registry and the utility inside the registry is likely only to be\navailable once your application's configuration is at least partially\ncompleted. A normal decorator would fail as it would be executed before the\nconfiguration had even begun.\n\nHowever, using :term:`Venusian`, the decorator could be written as follows:\n\n.. code-block:: python\n   :linenos:\n\n   import venusian\n   from mypackage.interfaces import IMyUtility\n\n   class registerFunction(object):\n\n       def __init__(self, path):\n           self.path = path\n\n       def register(self, scanner, name, wrapped):\n           registry = scanner.config.registry\n           registry.getUtility(IMyUtility).register(\n               self.path, wrapped)\n\n       def __call__(self, wrapped):\n           venusian.attach(wrapped, self.register)\n           return wrapped\n\nThis decorator could then be used to register functions throughout your code:\n\n.. code-block:: python\n   :linenos:\n\n   @registerFunction('/some/path')\n   def my_function():\n       do_stuff()\n\nHowever, the utility would only be looked up when a :term:`scan` was performed,\nenabling you to set up the utility in advance:\n\n.. code-block:: python\n   :linenos:\n\n   from zope.interface import implementer\n\n   from wsgiref.simple_server import make_server\n   from pyramid.config import Configurator\n   from mypackage.interfaces import IMyUtility\n\n   @implementer(IMyUtility)\n   class UtilityImplementation:\n\n       def __init__(self):\n           self.registrations = {}\n\n       def register(self, path, callable_):\n           self.registrations[path] = callable_\n\n   if __name__ == '__main__':\n       config = Configurator()\n       config.registry.registerUtility(UtilityImplementation())\n       config.scan()\n       app = config.make_wsgi_app()\n       server = make_server('0.0.0.0', 8080, app)\n       server.serve_forever()\n\nFor full details, please read the `Venusian documentation\n<http://docs.repoze.org/venusian>`_.\n\n.. _registering_tweens:\n\nRegistering Tweens\n------------------\n\n.. versionadded:: 1.2\n   Tweens\n\nA :term:`tween` (a contraction of the word \"between\") is a bit of code that\nsits between the Pyramid router's main request handling function and the\nupstream WSGI component that uses :app:`Pyramid` as its \"app\".  This is a\nfeature that may be used by Pyramid framework extensions to provide, for\nexample, Pyramid-specific view timing support bookkeeping code that examines\nexceptions before they are returned to the upstream WSGI application.  Tweens\nbehave a bit like :term:`WSGI` :term:`middleware`, but they have the benefit of\nrunning in a context in which they have access to the Pyramid :term:`request`,\n:term:`response`, and :term:`application registry`, as well as the Pyramid\nrendering machinery.\n\nCreating a Tween\n~~~~~~~~~~~~~~~~\n\nTo create a tween, you must write a \"tween factory\".  A tween factory must be a\nglobally importable callable which accepts two arguments: ``handler`` and\n``registry``.  ``handler`` will be either the main Pyramid request handling\nfunction or another tween.  ``registry`` will be the Pyramid :term:`application\nregistry` represented by this Configurator.  A tween factory must return the\ntween (a callable object) when it is called.\n\nA tween is called with a single argument, ``request``, which is the\n:term:`request` created by Pyramid's router when it receives a WSGI request. A\ntween should return a :term:`response`, usually the one generated by the\ndownstream Pyramid application.\n\nYou can write the tween factory as a simple closure-returning function:\n\n.. code-block:: python\n    :linenos:\n\n    def simple_tween_factory(handler, registry):\n        # one-time configuration code goes here\n\n        def simple_tween(request):\n            # code to be executed for each request before\n            # the actual application code goes here\n\n            response = handler(request)\n\n            # code to be executed for each request after\n            # the actual application code goes here\n\n            return response\n\n        return simple_tween\n\nAlternatively, the tween factory can be a class with the ``__call__`` magic\nmethod:\n\n.. code-block:: python\n    :linenos:\n\n    class simple_tween_factory(object):\n        def __init__(self, handler, registry):\n            self.handler = handler\n            self.registry = registry\n\n            # one-time configuration code goes here\n\n        def __call__(self, request):\n            # code to be executed for each request before\n            # the actual application code goes here\n\n            response = self.handler(request)\n\n            # code to be executed for each request after\n            # the actual application code goes here\n\n            return response\n\nYou should avoid mutating any state on the tween instance. The tween is invoked\nonce per request and any shared mutable state needs to be carefully handled to\navoid any race conditions.\n\nThe closure style performs slightly better and enables you to conditionally\nomit the tween from the request processing pipeline (see the following timing\ntween example), whereas the class style makes it easier to have shared mutable\nstate and allows subclassing.\n\nHere's a complete example of a tween that logs the time spent processing each\nrequest:\n\n.. code-block:: python\n    :linenos:\n\n    # in a module named myapp.tweens\n\n    import time\n    from pyramid.settings import asbool\n    import logging\n\n    log = logging.getLogger(__name__)\n\n    def timing_tween_factory(handler, registry):\n        if asbool(registry.settings.get('do_timing')):\n            # if timing support is enabled, return a wrapper\n            def timing_tween(request):\n                start = time.time()\n                try:\n                    response = handler(request)\n                finally:\n                    end = time.time()\n                    log.debug('The request took %s seconds' %\n                              (end - start))\n                return response\n            return timing_tween\n        # if timing support is not enabled, return the original\n        # handler\n        return handler\n\nIn the above example, the tween factory defines a ``timing_tween`` tween and\nreturns it if ``asbool(registry.settings.get('do_timing'))`` is true.  It\notherwise simply returns the handler which it was given.  The\n``registry.settings`` attribute is a handle to the deployment settings provided\nby the user (usually in an ``.ini`` file).  In this case, if the user has\ndefined a ``do_timing`` setting and that setting is ``True``, the user has said\nthey want to do timing, so the tween factory returns the timing tween; it\notherwise just returns the handler it has been provided, preventing any timing.\n\nThe example timing tween simply records the start time, calls the downstream\nhandler, logs the number of seconds consumed by the downstream handler, and\nreturns the response.\n\nRegistering an Implicit Tween Factory\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce you've created a tween factory, you can register it into the implicit\ntween chain using the :meth:`pyramid.config.Configurator.add_tween` method\nusing its :term:`dotted Python name`.\n\nHere's an example of registering a tween factory as an \"implicit\" tween in a\nPyramid application:\n\n.. code-block:: python\n    :linenos:\n\n    from pyramid.config import Configurator\n    config = Configurator()\n    config.add_tween('myapp.tweens.timing_tween_factory')\n\nNote that you must use a :term:`dotted Python name` as the first argument to\n:meth:`pyramid.config.Configurator.add_tween`; this must point at a tween\nfactory.  You cannot pass the tween factory object itself to the method: it\nmust be :term:`dotted Python name` that points to a globally importable object.\nIn the above example, we assume that a ``timing_tween_factory`` tween factory\nwas defined in a module named ``myapp.tweens``, so the tween factory is\nimportable as ``myapp.tweens.timing_tween_factory``.\n\nWhen you use :meth:`pyramid.config.Configurator.add_tween`, you're instructing\nthe system to use your tween factory at startup time unless the user has\nprovided an explicit tween list in their configuration.  This is what's meant\nby an \"implicit\" tween.  A user can always elect to supply an explicit tween\nlist, reordering or disincluding implicitly added tweens.  See\n:ref:`explicit_tween_ordering` for more information about explicit tween\nordering.\n\nIf more than one call to :meth:`pyramid.config.Configurator.add_tween` is made\nwithin a single application configuration, the tweens will be chained together\nat application startup time.  The *first* tween factory added via ``add_tween``\nwill be called with the Pyramid exception view tween factory as its ``handler``\nargument, then the tween factory added directly after that one will be called\nwith the result of the first tween factory as its ``handler`` argument, and so\non, ad infinitum until all tween factories have been called. The Pyramid router\nwill use the outermost tween produced by this chain (the tween generated by the\nvery last tween factory added) as its request handler function.  For example:\n\n.. code-block:: python\n    :linenos:\n\n    from pyramid.config import Configurator\n\n    config = Configurator()\n    config.add_tween('myapp.tween_factory1')\n    config.add_tween('myapp.tween_factory2')\n\nThe above example will generate an implicit tween chain that looks like this::\n\n    INGRESS (implicit)\n    myapp.tween_factory2\n    myapp.tween_factory1\n    pyramid.tweens.excview_tween_factory (implicit)\n    MAIN (implicit)\n\nSuggesting Implicit Tween Ordering\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBy default, as described above, the ordering of the chain is controlled\nentirely by the relative ordering of calls to\n:meth:`pyramid.config.Configurator.add_tween`.  However, the caller of\n``add_tween`` can provide an optional hint that can influence the implicit\ntween chain ordering by supplying ``under`` or ``over`` (or both) arguments to\n:meth:`~pyramid.config.Configurator.add_tween`.  These hints are only used when\nan explicit tween ordering is not used. See :ref:`explicit_tween_ordering` for\na description of how to set an explicit tween ordering.\n\nAllowable values for ``under`` or ``over`` (or both) are:\n\n- ``None`` (the default),\n\n- a :term:`dotted Python name` to a tween factory: a string representing the\n  predicted dotted name of a tween factory added in a call to ``add_tween`` in\n  the same configuration session,\n\n- one of the constants :attr:`pyramid.tweens.MAIN`,\n  :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`, or\n\n- an iterable of any combination of the above. This allows the user to specify\n  fallbacks if the desired tween is not included, as well as compatibility\n  with multiple other tweens.\n\nEffectively, ``over`` means \"closer to the request ingress than\" and ``under``\nmeans \"closer to the main Pyramid application than\". You can think of an onion\nwith outer layers over the inner layers, the application being under all the\nlayers at the center.\n\nFor example, the following call to\n:meth:`~pyramid.config.Configurator.add_tween` will attempt to place the tween\nfactory represented by ``myapp.tween_factory`` directly \"above\" (in ``ptweens``\norder) the main Pyramid request handler.\n\n.. code-block:: python\n   :linenos:\n\n   import pyramid.tweens\n\n   config.add_tween('myapp.tween_factory', over=pyramid.tweens.MAIN)\n\nThe above example will generate an implicit tween chain that looks like this::\n\n    INGRESS (implicit)\n    pyramid.tweens.excview_tween_factory (implicit)\n    myapp.tween_factory\n    MAIN (implicit)\n\nLikewise, calling the following call to\n:meth:`~pyramid.config.Configurator.add_tween` will attempt to place this tween\nfactory \"above\" the main handler but \"below\" a separately added tween factory:\n\n.. code-block:: python\n   :linenos:\n\n   import pyramid.tweens\n\n   config.add_tween('myapp.tween_factory1',\n                    over=pyramid.tweens.MAIN)\n   config.add_tween('myapp.tween_factory2',\n                    over=pyramid.tweens.MAIN,\n                    under='myapp.tween_factory1')\n\nThe above example will generate an implicit tween chain that looks like this::\n\n    INGRESS (implicit)\n    pyramid.tweens.excview_tween_factory (implicit)\n    myapp.tween_factory1\n    myapp.tween_factory2\n    MAIN (implicit)\n\nSpecifying neither ``over`` nor ``under`` is equivalent to specifying\n``under=INGRESS``.\n\nIf all options for ``under`` (or ``over``) cannot be found in the current\nconfiguration, it is an error. If some options are specified purely for\ncompatibilty with other tweens, just add a fallback of ``MAIN`` or ``INGRESS``.\nFor example, ``under=('someothertween', 'someothertween2', INGRESS)``. This\nconstraint will require the tween to be located under the ``someothertween``\ntween, the ``someothertween2`` tween, and ``INGRESS``. If any of these is not\nin the current configuration, this constraint will only organize itself based\non the tweens that are present.\n\n.. _explicit_tween_ordering:\n\nExplicit Tween Ordering\n~~~~~~~~~~~~~~~~~~~~~~~\n\nImplicit tween ordering is obviously only best-effort.  Pyramid will attempt to\nprovide an implicit order of tweens as best it can using hints provided by\ncalls to :meth:`~pyramid.config.Configurator.add_tween`.  But because it's only\nbest-effort, if very precise tween ordering is required, the only surefire way\nto get it is to use an explicit tween order.  The deploying user can override\nthe implicit tween inclusion and ordering implied by calls to\n:meth:`~pyramid.config.Configurator.add_tween` entirely by using the\n``pyramid.tweens`` settings value.  When used, this settings value must be a\nlist of Python dotted names which will override the ordering (and inclusion) of\ntween factories in the implicit tween chain.  For example:\n\n.. code-block:: ini\n   :linenos:\n\n   [app:main]\n   use = egg:MyApp\n   pyramid.reload_templates = true\n   pyramid.debug_authorization = false\n   pyramid.debug_notfound = false\n   pyramid.debug_routematch = false\n   pyramid.debug_templates = true\n   pyramid.tweens = myapp.my_cool_tween_factory\n                    pyramid.tweens.excview_tween_factory\n\nIn the above configuration, calls made during configuration to\n:meth:`pyramid.config.Configurator.add_tween` are ignored, and the user is\ntelling the system to use the tween factories he has listed in the\n``pyramid.tweens`` configuration setting (each is a :term:`dotted Python name`\nwhich points to a tween factory) instead of any tween factories added via\n:meth:`pyramid.config.Configurator.add_tween`.  The *first* tween factory in\nthe ``pyramid.tweens`` list will be used as the producer of the effective\n:app:`Pyramid` request handling function; it will wrap the tween factory\ndeclared directly \"below\" it, ad infinitum.  The \"main\" Pyramid request handler\nis implicit, and always \"at the bottom\".\n\n.. note::\n\n   Pyramid's own :term:`exception view` handling logic is implemented as a\n   tween factory function: :func:`pyramid.tweens.excview_tween_factory`.  If\n   Pyramid exception view handling is desired, and tween factories are\n   specified via the ``pyramid.tweens`` configuration setting, the\n   :func:`pyramid.tweens.excview_tween_factory` function must be added to the\n   ``pyramid.tweens`` configuration setting list explicitly.  If it is not\n   present, Pyramid will not perform exception view handling.\n\nTween Conflicts and Ordering Cycles\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nPyramid will prevent the same tween factory from being added to the tween chain\nmore than once using configuration conflict detection.  If you wish to add the\nsame tween factory more than once in a configuration, you should either: (a)\nuse a tween factory that is a separate globally importable instance object from\nthe factory that it conflicts with; (b) use a function or class as a tween\nfactory with the same logic as the other tween factory it conflicts with, but\nwith a different ``__name__`` attribute; or (c) call\n:meth:`pyramid.config.Configurator.commit` between calls to\n:meth:`pyramid.config.Configurator.add_tween`.\n\nIf a cycle is detected in implicit tween ordering when ``over`` and ``under``\nare used in any call to ``add_tween``, an exception will be raised at startup\ntime.\n\nDisplaying Tween Ordering\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe ``ptweens`` command-line utility can be used to report the current implict\nand explicit tween chains used by an application.  See\n:ref:`displaying_tweens`.\n\n.. _registering_thirdparty_predicates:\n\nAdding a Third Party View, Route, or Subscriber Predicate\n---------------------------------------------------------\n\n.. versionadded:: 1.4\n\n.. _view_and_route_predicates:\n\nView and Route Predicates\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nView and route predicates used during configuration allow you to narrow the set\nof circumstances under which a view or route will match.  For example, the\n``request_method`` view predicate can be used to ensure a view callable is only\ninvoked when the request's method is ``POST``:\n\n.. code-block:: python\n\n    @view_config(request_method='POST')\n    def someview(request):\n        ...\n\nLikewise, a similar predicate can be used as a *route* predicate:\n\n.. code-block:: python\n\n    config.add_route('name', '/foo', request_method='POST')\n\nMany other built-in predicates exists (``request_param``, and others).  You can\nadd third-party predicates to the list of available predicates by using one of\n:meth:`pyramid.config.Configurator.add_view_predicate` or\n:meth:`pyramid.config.Configurator.add_route_predicate`.  The former adds a\nview predicate, the latter a route predicate.\n\nWhen using one of those APIs, you pass a *name* and a *factory* to add a\npredicate during Pyramid's configuration stage.  For example:\n\n.. code-block:: python\n\n    config.add_view_predicate('content_type', ContentTypePredicate)\n\nThe above example adds a new predicate named ``content_type`` to the list of\navailable predicates for views.  This will allow the following view\nconfiguration statement to work:\n\n.. code-block:: python\n   :linenos:\n\n   @view_config(content_type='File')\n   def aview(request): ...\n\nThe first argument to :meth:`pyramid.config.Configurator.add_view_predicate`,\nthe name, is a string representing the name that is expected to be passed to\n``view_config`` (or its imperative analogue ``add_view``).\n\nThe second argument is a view or route predicate factory, or a :term:`dotted\nPython name` which refers to a view or route predicate factory.  A view or\nroute predicate factory is most often a class with a constructor\n(``__init__``), a ``text`` method, a ``phash`` method, and a ``__call__``\nmethod. For example:\n\n.. code-block:: python\n    :linenos:\n\n    class ContentTypePredicate(object):\n        def __init__(self, val, config):\n            self.val = val\n\n        def text(self):\n            return 'content_type = %s' % (self.val,)\n\n        phash = text\n\n        def __call__(self, context, request):\n            return getattr(context, 'content_type', None) == self.val\n\nThe constructor of a predicate factory takes two arguments: ``val`` and\n``config``.  The ``val`` argument will be the argument passed to\n``view_config`` (or ``add_view``).  In the example above, it will be the string\n``File``.  The second argument, ``config``, will be the Configurator instance\nat the time of configuration.\n\nThe ``text`` method must return a string.  It should be useful to describe the\nbehavior of the predicate in error messages.\n\nThe ``phash`` method must return a string or a sequence of strings.  It's most\noften the same as ``text``, as long as ``text`` uniquely describes the\npredicate's name and the value passed to the constructor.  If ``text`` is more\ngeneral, or doesn't describe things that way, ``phash`` should return a string\nwith the name and the value serialized.  The result of ``phash`` is not seen in\noutput anywhere, it just informs the uniqueness constraints for view\nconfiguration.\n\nThe ``__call__`` method of a predicate factory must accept a resource\n(``context``) and a request, and must return ``True`` or ``False``.  It is the\n\"meat\" of the predicate.\n\nYou can use the same predicate factory as both a view predicate and as a route\npredicate, but you'll need to call ``add_view_predicate`` and\n``add_route_predicate`` separately with the same factory.\n\n.. _subscriber_predicates:\n\nSubscriber Predicates\n~~~~~~~~~~~~~~~~~~~~~\n\nSubscriber predicates work almost exactly like view and route predicates. They\nnarrow the set of circumstances in which a subscriber will be called. There are\nseveral minor differences between a subscriber predicate and a view or route\npredicate:\n\n- There are no default subscriber predicates.  You must register one to use\n  one.\n\n- The ``__call__`` method of a subscriber predicate accepts a single ``event``\n  object instead of a ``context`` and a ``request``.\n\n- Not every subscriber predicate can be used with every event type.  Some\n  subscriber predicates will assume a certain event type.\n\nHere's an example of a subscriber predicate that can be used in conjunction\nwith a subscriber that subscribes to the :class:`pyramid.events.NewRequest`\nevent type.\n\n.. code-block:: python\n    :linenos:\n\n    class RequestPathStartsWith(object):\n        def __init__(self, val, config):\n            self.val = val\n\n        def text(self):\n            return 'path_startswith = %s' % (self.val,)\n\n        phash = text\n\n        def __call__(self, event):\n            return event.request.path.startswith(self.val)\n\nOnce you've created a subscriber predicate, it may registered via\n:meth:`pyramid.config.Configurator.add_subscriber_predicate`.  For example:\n\n.. code-block:: python\n\n    config.add_subscriber_predicate(\n        'request_path_startswith', RequestPathStartsWith)\n\nOnce a subscriber predicate is registered, you can use it in a call to\n:meth:`pyramid.config.Configurator.add_subscriber` or to\n:class:`pyramid.events.subscriber`.  Here's an example of using the previously\nregistered ``request_path_startswith`` predicate in a call to\n:meth:`~pyramid.config.Configurator.add_subscriber`:\n\n.. code-block:: python\n    :linenos:\n\n    # define a subscriber in your code\n\n    def yosubscriber(event):\n        event.request.yo = 'YO!'\n\n    # and at configuration time\n\n    config.add_subscriber(yosubscriber, NewRequest,\n           request_path_startswith='/add_yo')\n\nHere's the same subscriber/predicate/event-type combination used via\n:class:`~pyramid.events.subscriber`.\n\n.. code-block:: python\n    :linenos:\n\n    from pyramid.events import subscriber\n\n    @subscriber(NewRequest, request_path_startswith='/add_yo')\n    def yosubscriber(event):\n        event.request.yo = 'YO!'\n\nIn either of the above configurations, the ``yosubscriber`` callable will only\nbe called if the request path starts with ``/add_yo``.  Otherwise the event\nsubscriber will not be called.\n\nNote that the ``request_path_startswith`` subscriber you defined can be used\nwith events that have a ``request`` attribute, but not ones that do not.  So,\nfor example, the predicate can be used with subscribers registered for\n:class:`pyramid.events.NewRequest` and :class:`pyramid.events.ContextFound`\nevents, but it cannot be used with subscribers registered for\n:class:`pyramid.events.ApplicationCreated` because the latter type of event has\nno ``request`` attribute.  The point being, unlike route and view predicates,\nnot every type of subscriber predicate will necessarily be applicable for use\nin every subscriber registration.  It is not the responsibility of the\npredicate author to make every predicate make sense for every event type; it is\nthe responsibility of the predicate consumer to use predicates that make sense\nfor a particular event type registration.\n\n\n.. index::\n   single: view derivers\n\n.. _view_derivers:\n\nView Derivers\n-------------\n\n.. versionadded:: 1.7\n\nEvery URL processed by :app:`Pyramid` is matched against a custom view\npipeline. See :ref:`router_chapter` for how this works. The view pipeline\nitself is built from the user-supplied :term:`view callable`, which is then\ncomposed with :term:`view derivers <view deriver>`. A view deriver is a\ncomposable element of the view pipeline which is used to wrap a view with\nadded functionality. View derivers are very similar to the ``decorator``\nargument to :meth:`pyramid.config.Configurator.add_view`, except that they have\nthe option to execute for every view in the application.\n\nIt is helpful to think of a :term:`view deriver` as middleware for views.\nUnlike tweens or WSGI middleware which are scoped to the application itself,\na view deriver is invoked once per view in the application, and can use\nconfiguration options from the view to customize its behavior.\n\nBuilt-in View Derivers\n~~~~~~~~~~~~~~~~~~~~~~\n\nThere are several built-in view derivers that :app:`Pyramid` will automatically\napply to any view. Below they are defined in order from furthest to closest to\nthe user-defined :term:`view callable`:\n\n``secured_view``\n\n  Enforce the ``permission`` defined on the view. This element is a no-op if no\n  permission is defined. Note there will always be a permission defined if a\n  default permission was assigned via\n  :meth:`pyramid.config.Configurator.set_default_permission`.\n\n  This element will also output useful debugging information when\n  ``pyramid.debug_authorization`` is enabled.\n\n``owrapped_view``\n\n  Invokes the wrapped view defined by the ``wrapper`` option.\n\n``http_cached_view``\n\n  Applies cache control headers to the response defined by the ``http_cache``\n  option. This element is a no-op if the ``pyramid.prevent_http_cache`` setting\n  is enabled or the ``http_cache`` option is ``None``.\n\n``decorated_view``\n\n  Wraps the view with the decorators from the ``decorator`` option.\n\n``rendered_view``\n\n  Adapts the result of the :term:`view callable` into a :term:`response`\n  object. Below this point the result may be any Python object.\n\n``mapped_view``\n\n  Applies the :term:`view mapper` defined by the ``mapper`` option or the\n  application's default view mapper to the :term:`view callable`. This\n  is always the closest deriver to the user-defined view and standardizes the\n  view pipeline interface to accept ``(context, request)`` from all previous\n  view derivers.\n\nCustom View Derivers\n~~~~~~~~~~~~~~~~~~~~\n\nIt is possible to define custom view derivers which will affect all views in an\napplication. There are many uses for this, but most will likely be centered\naround monitoring and security. In order to register a custom :term:`view\nderiver`, you should create a callable that conforms to the\n:class:`pyramid.interfaces.IViewDeriver` interface, and then register it with\nyour application using :meth:`pyramid.config.Configurator.add_view_deriver`.\nFor example, below is a callable that can provide timing information for the\nview pipeline:\n\n.. code-block:: python\n   :linenos:\n\n   import time\n\n   def timing_view(view, info):\n       def wrapper_view(context, request):\n           start = time.time()\n           response = view(context, request)\n           end = time.time()\n           response.headers['X-View-Performance'] = '%.3f' % (end - start,)\n       return wrapper_view\n\n   config.add_view_deriver(timing_view, 'timing view')\n\nView derivers are unique in that they have access to most of the options\npassed to :meth:`pyramid.config.Configurator.add_view` in order to decide what\nto do, and they have a chance to affect every view in the application.\n\nLet's look at one more example which will protect views by requiring a CSRF\ntoken unless ``disable_csrf=True`` is passed to the view:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n   from pyramid.session import check_csrf_token\n\n   def require_csrf_view(view, info):\n       wrapper_view = view\n       if not info.options.get('disable_csrf', False):\n           def wrapper_view(context, request):\n               if request.method == 'POST':\n                   check_csrf_token(request)\n               return view(context, request)\n       return wrapper_view\n\n   require_csrf_view.options = ('disable_csrf',)\n\n   config.add_view_deriver(require_csrf_view, 'require_csrf_view')\n\n   def protected_view(request):\n       return Response('protected')\n\n   def unprotected_view(request):\n       return Response('unprotected')\n\n   config.add_view(protected_view, name='safe')\n   config.add_view(unprotected_view, name='unsafe', disable_csrf=True)\n\nNavigating to ``/safe`` with a POST request will then fail when the call to\n:func:`pyramid.session.check_csrf_token` raises a\n:class:`pyramid.exceptions.BadCSRFToken` exception. However, ``/unsafe`` will\nnot error.\n\nOrdering View Derivers\n~~~~~~~~~~~~~~~~~~~~~~\n\nBy default, every new view deriver is added between the ``decorated_view`` and\n``rendered_view`` built-in derivers. It is possible to customize this ordering\nusing the ``over`` and ``under`` options. Each option can use the names of\nother view derivers in order to specify an ordering. There should rarely be a\nreason to worry about the ordering of the derivers.\n\nBoth ``over`` and ``under`` may also be iterables of constraints. For either\noption, if one or more constraints was defined, at least one must be satisfied,\nelse a :class:`pyramid.exceptions.ConfigurationError` will be raised. This may\nbe used to define fallback constraints if another deriver is missing.\n\nIt is not possible to add a view deriver under the ``mapped_view`` as the\n:term:`view mapper` is intimately tied to the signature of the user-defined\n:term:`view callable`. If you simply need to know what the original view\ncallable was, it can be found as ``info.original_view`` on the provided\n:class:`pyramid.interfaces.IViewDeriverInfo` object passed to every view\nderiver.\n\n.. warning::\n\n   Any view derivers defined ``under`` the ``rendered_view`` are not\n   guaranteed to receive a valid response object. Rather they will receive the\n   result from the :term:`view mapper` which is likely the original response\n   returned from the view. This is possibly a dictionary for a renderer but it\n   may be any Python object that may be adapted into a response.\n",
            "new_file_content": ".. _hooks_chapter:\n\nUsing Hooks\n===========\n\n\"Hooks\" can be used to influence the behavior of the :app:`Pyramid` framework\nin various ways.\n\n.. index::\n   single: not found view\n\n.. _changing_the_notfound_view:\n\nChanging the Not Found View\n---------------------------\n\nWhen :app:`Pyramid` can't map a URL to view code, it invokes a :term:`Not Found\nView`, which is a :term:`view callable`. The default Not Found View can be\noverridden through application configuration.\n\nIf your application uses :term:`imperative configuration`, you can replace the\nNot Found View by using the\n:meth:`pyramid.config.Configurator.add_notfound_view` method:\n\n.. code-block:: python\n   :linenos:\n\n   def notfound(request):\n       return Response('Not Found, dude', status='404 Not Found')\n\n   def main(globals, **settings):\n       config = Configurator()\n       config.add_notfound_view(notfound)\n\nThe :term:`Not Found View` callable is a view callable like any other.\n\nIf your application instead uses :class:`pyramid.view.view_config` decorators\nand a :term:`scan`, you can replace the Not Found View by using the\n:class:`pyramid.view.notfound_view_config` decorator:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import notfound_view_config\n\n   @notfound_view_config()\n   def notfound(request):\n       return Response('Not Found, dude', status='404 Not Found')\n\n   def main(globals, **settings):\n       config = Configurator()\n       config.scan()\n\nThis does exactly what the imperative example above showed.\n\nYour application can define *multiple* Not Found Views if necessary.  Both\n:meth:`pyramid.config.Configurator.add_notfound_view` and\n:class:`pyramid.view.notfound_view_config` take most of the same arguments as\n:class:`pyramid.config.Configurator.add_view` and\n:class:`pyramid.view.view_config`, respectively.  This means that Not Found\nViews can carry predicates limiting their applicability.  For example:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import notfound_view_config\n\n   @notfound_view_config(request_method='GET')\n   def notfound_get(request):\n       return Response('Not Found during GET, dude', status='404 Not Found')\n\n   @notfound_view_config(request_method='POST')\n   def notfound_post(request):\n       return Response('Not Found during POST, dude', status='404 Not Found')\n\n   def main(globals, **settings):\n      config = Configurator()\n      config.scan()\n\nThe ``notfound_get`` view will be called when a view could not be found and the\nrequest method was ``GET``.  The ``notfound_post`` view will be called when a\nview could not be found and the request method was ``POST``.\n\nLike any other view, the Not Found View must accept at least a ``request``\nparameter, or both ``context`` and ``request``.  The ``request`` is the current\n:term:`request` representing the denied action.  The ``context`` (if used in\nthe call signature) will be the instance of the\n:exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the view to\nbe called.\n\nBoth :meth:`pyramid.config.Configurator.add_notfound_view` and\n:class:`pyramid.view.notfound_view_config` can be used to automatically\nredirect requests to slash-appended routes. See\n:ref:`redirecting_to_slash_appended_routes` for examples.\n\nHere's some sample code that implements a minimal :term:`Not Found View`\ncallable:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.httpexceptions import HTTPNotFound\n\n   def notfound(request):\n       return HTTPNotFound()\n\n.. note::\n\n   When a Not Found View callable is invoked, it is passed a :term:`request`.\n   The ``exception`` attribute of the request will be an instance of the\n   :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that caused the Not\n   Found View to be called.  The value of ``request.exception.message`` will be\n   a value explaining why the Not Found exception was raised.  This message has\n   different values depending on whether the ``pyramid.debug_notfound``\n   environment setting is true or false.\n\n.. note::\n\n   Both :meth:`pyramid.config.Configurator.add_notfound_view` and\n   :class:`pyramid.view.notfound_view_config` are new as of Pyramid 1.3.\n   Older Pyramid documentation instructed users to use ``add_view`` instead,\n   with a ``context`` of ``HTTPNotFound``.  This still works; the convenience\n   method and decorator are just wrappers around this functionality.\n\n.. warning::\n\n   When a Not Found View callable accepts an argument list as described in\n   :ref:`request_and_context_view_definitions`, the ``context`` passed as the\n   first argument to the view callable will be the\n   :exc:`~pyramid.httpexceptions.HTTPNotFound` exception instance.  If\n   available, the resource context will still be available as\n   ``request.context``.\n\n.. index::\n   single: forbidden view\n\n.. _changing_the_forbidden_view:\n\nChanging the Forbidden View\n---------------------------\n\nWhen :app:`Pyramid` can't authorize execution of a view based on the\n:term:`authorization policy` in use, it invokes a :term:`forbidden view`. The\ndefault forbidden response has a 403 status code and is very plain, but the\nview which generates it can be overridden as necessary.\n\nThe :term:`forbidden view` callable is a view callable like any other.  The\n:term:`view configuration` which causes it to be a \"forbidden\" view consists of\nusing the :meth:`pyramid.config.Configurator.add_forbidden_view` API or the\n:class:`pyramid.view.forbidden_view_config` decorator.\n\nFor example, you can add a forbidden view by using the\n:meth:`pyramid.config.Configurator.add_forbidden_view` method to register a\nforbidden view:\n\n.. code-block:: python\n   :linenos:\n\n   def forbidden(request):\n       return Response('forbidden')\n\n   def main(globals, **settings):\n       config = Configurator()\n       config.add_forbidden_view(forbidden_view)\n\nIf instead you prefer to use decorators and a :term:`scan`, you can use the\n:class:`pyramid.view.forbidden_view_config` decorator to mark a view callable\nas a forbidden view:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import forbidden_view_config\n\n   @forbidden_view_config()\n   def forbidden(request):\n       return Response('forbidden')\n\n   def main(globals, **settings):\n      config = Configurator()\n      config.scan()\n\nLike any other view, the forbidden view must accept at least a ``request``\nparameter, or both ``context`` and ``request``.  If a forbidden view callable\naccepts both ``context`` and ``request``, the HTTP Exception is passed as\ncontext. The ``context`` as found by the router when the view was denied (which\nyou normally would expect) is available as ``request.context``.  The\n``request`` is the  current :term:`request` representing the denied action.\n\nHere's some sample code that implements a minimal forbidden view:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import view_config\n   from pyramid.response import Response\n\n   def forbidden_view(request):\n       return Response('forbidden')\n\n.. note::\n\n   When a forbidden view callable is invoked, it is passed a :term:`request`.\n   The ``exception`` attribute of the request will be an instance of the\n   :exc:`~pyramid.httpexceptions.HTTPForbidden` exception that caused the\n   forbidden view to be called.  The value of ``request.exception.message``\n   will be a value explaining why the forbidden exception was raised, and\n   ``request.exception.result`` will be extended information about the\n   forbidden exception.  These messages have different values depending on\n   whether the ``pyramid.debug_authorization`` environment setting is true or\n   false.\n\n.. index::\n   single: request factory\n\n.. _changing_the_request_factory:\n\nChanging the Request Factory\n----------------------------\n\nWhenever :app:`Pyramid` handles a request from a :term:`WSGI` server, it\ncreates a :term:`request` object based on the WSGI environment it has been\npassed.  By default, an instance of the :class:`pyramid.request.Request` class\nis created to represent the request object.\n\nThe class (a.k.a., \"factory\") that :app:`Pyramid` uses to create a request\nobject instance can be changed by passing a ``request_factory`` argument to the\nconstructor of the :term:`configurator`.  This argument can be either a\ncallable or a :term:`dotted Python name` representing a callable.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.request import Request\n\n   class MyRequest(Request):\n       pass\n\n   config = Configurator(request_factory=MyRequest)\n\nIf you're doing imperative configuration, and you'd rather do it after you've\nalready constructed a :term:`configurator`, it can also be registered via the\n:meth:`pyramid.config.Configurator.set_request_factory` method:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n   from pyramid.request import Request\n\n   class MyRequest(Request):\n       pass\n\n   config = Configurator()\n   config.set_request_factory(MyRequest)\n\n.. index::\n   single: request method\n\n.. _adding_request_method:\n\nAdding Methods or Properties to a Request Object\n------------------------------------------------\n\n.. versionadded:: 1.4\n\nSince each Pyramid application can only have one :term:`request` factory,\n:ref:`changing the request factory <changing_the_request_factory>` is not that\nextensible, especially if you want to build composable features (e.g., Pyramid\nadd-ons and plugins).\n\nA lazy property can be registered to the request object via the\n:meth:`pyramid.config.Configurator.add_request_method` API. This allows you to\nspecify a callable that will be available on the request object, but will not\nactually execute the function until accessed.\n\n.. warning::\n\n   This will silently override methods and properties from :term:`request\n   factory` that have the same name.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n\n   def total(request, *args):\n       return sum(args)\n\n   def prop(request):\n       print(\"getting the property\")\n       return \"the property\"\n\n   config = Configurator()\n   config.add_request_method(total)\n   config.add_request_method(prop, reify=True)\n\nIn the above example, ``total`` is added as a method. However, ``prop`` is\nadded as a property and its result is cached per-request by setting\n``reify=True``. This way, we eliminate the overhead of running the function\nmultiple times.\n\n   >>> request.total(1, 2, 3)\n   6\n   >>> request.prop\n   getting the property\n   the property\n   >>> request.prop\n   the property\n\nTo not cache the result of ``request.prop``, set ``property=True`` instead of\n``reify=True``.\n\nHere is an example of passing a class to ``Configurator.add_request_method``:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n   from pyramid.decorator import reify\n\n   class ExtraStuff(object):\n\n       def __init__(self, request):\n           self.request = request\n\n       def total(self, *args):\n           return sum(args)\n\n       # use @property if you don't want to cache the result\n       @reify\n       def prop(self):\n           print(\"getting the property\")\n           return \"the property\"\n\n   config = Configurator()\n   config.add_request_method(ExtraStuff, 'extra', reify=True)\n\nWe attach and cache an object named ``extra`` to the ``request`` object.\n\n   >>> request.extra.total(1, 2, 3)\n   6\n   >>> request.extra.prop\n   getting the property\n   the property\n   >>> request.extra.prop\n   the property\n\n.. index::\n   single: response factory\n\n.. _changing_the_response_factory:\n\nChanging the Response Factory\n-----------------------------\n\n.. versionadded:: 1.6\n\nWhenever :app:`Pyramid` returns a response from a view, it creates a\n:term:`response` object.  By default, an instance of the\n:class:`pyramid.response.Response` class is created to represent the response\nobject.\n\nThe factory that :app:`Pyramid` uses to create a response object instance can\nbe changed by passing a :class:`pyramid.interfaces.IResponseFactory` argument\nto the constructor of the :term:`configurator`.  This argument can be either a\ncallable or a :term:`dotted Python name` representing a callable.\n\nThe factory takes a single positional argument, which is a :term:`Request`\nobject. The argument may be ``None``.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n\n   class MyResponse(Response):\n       pass\n\n   config = Configurator(response_factory=lambda r: MyResponse())\n\nIf you're doing imperative configuration and you'd rather do it after you've\nalready constructed a :term:`configurator`, it can also be registered via the\n:meth:`pyramid.config.Configurator.set_response_factory` method:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n   from pyramid.response import Response\n\n   class MyResponse(Response):\n       pass\n\n   config = Configurator()\n   config.set_response_factory(lambda r: MyResponse())\n\n.. index::\n   single: before render event\n   single: adding renderer globals\n\n.. _beforerender_event:\n\nUsing the Before Render Event\n-----------------------------\n\nSubscribers to the :class:`pyramid.events.BeforeRender` event may introspect\nand modify the set of :term:`renderer globals` before they are passed to a\n:term:`renderer`.  This event object iself has a dictionary-like interface that\ncan be used for this purpose.  For example:\n\n.. code-block:: python\n    :linenos:\n\n    from pyramid.events import subscriber\n    from pyramid.events import BeforeRender\n\n    @subscriber(BeforeRender)\n    def add_global(event):\n        event['mykey'] = 'foo'\n\nAn object of this type is sent as an event just before a :term:`renderer` is\ninvoked.\n\nIf a subscriber attempts to add a key that already exists in the renderer\nglobals dictionary, a :exc:`KeyError` is raised.  This limitation is enforced\nbecause event subscribers do not possess any relative ordering.  The set of\nkeys added to the renderer globals dictionary by all\n:class:`pyramid.events.BeforeRender` subscribers and renderer globals factories\nmust be unique.\n\nThe dictionary returned from the view is accessible through the\n:attr:`rendering_val` attribute of a :class:`~pyramid.events.BeforeRender`\nevent.\n\nSuppose you return ``{'mykey': 'somevalue', 'mykey2': 'somevalue2'}`` from your\nview callable, like so:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.view import view_config\n\n   @view_config(renderer='some_renderer')\n   def myview(request):\n       return {'mykey': 'somevalue', 'mykey2': 'somevalue2'}\n\n:attr:`rendering_val` can be used to access these values from the\n:class:`~pyramid.events.BeforeRender` object:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.events import subscriber\n   from pyramid.events import BeforeRender\n\n   @subscriber(BeforeRender)\n   def read_return(event):\n       # {'mykey': 'somevalue'} is returned from the view\n       print(event.rendering_val['mykey'])\n\nSee the API documentation for the :class:`~pyramid.events.BeforeRender` event\ninterface at :class:`pyramid.interfaces.IBeforeRender`.\n\n.. index::\n   single: response callback\n\n.. _using_response_callbacks:\n\nUsing Response Callbacks\n------------------------\n\nUnlike many other web frameworks, :app:`Pyramid` does not eagerly create a\nglobal response object.  Adding a :term:`response callback` allows an\napplication to register an action to be performed against whatever response\nobject is returned by a view, usually in order to mutate the response.\n\nThe :meth:`pyramid.request.Request.add_response_callback` method is used to\nregister a response callback.\n\nA response callback is a callable which accepts two positional parameters:\n``request`` and ``response``.  For example:\n\n.. code-block:: python\n   :linenos:\n\n   def cache_callback(request, response):\n       \"\"\"Set the cache_control max_age for the response\"\"\"\n       if request.exception is not None:\n           response.cache_control.max_age = 360\n   request.add_response_callback(cache_callback)\n\nNo response callback is called if an unhandled exception happens in application\ncode, or if the response object returned by a :term:`view callable` is invalid.\nResponse callbacks *are*, however, invoked when a :term:`exception view` is\nrendered successfully.  In such a case, the :attr:`request.exception` attribute\nof the request when it enters a response callback will be an exception object\ninstead of its default value of ``None``.\n\nResponse callbacks are called in the order they're added\n(first-to-most-recently-added).  All response callbacks are called *before* the\n:class:`~pyramid.events.NewResponse` event is sent.  Errors raised by response\ncallbacks are not handled specially.  They will be propagated to the caller of\nthe :app:`Pyramid` router application.\n\nA response callback has a lifetime of a *single* request.  If you want a\nresponse callback to happen as the result of *every* request, you must\nre-register the callback into every new request (perhaps within a subscriber of\na :class:`~pyramid.events.NewRequest` event).\n\n.. index::\n   single: finished callback\n\n.. _using_finished_callbacks:\n\nUsing Finished Callbacks\n------------------------\n\nA :term:`finished callback` is a function that will be called unconditionally\nby the :app:`Pyramid` :term:`router` at the very end of request processing. A\nfinished callback can be used to perform an action at the end of a request\nunconditionally.\n\nThe :meth:`pyramid.request.Request.add_finished_callback` method is used to\nregister a finished callback.\n\nA finished callback is a callable which accepts a single positional parameter:\n``request``.  For example:\n\n.. code-block:: python\n   :linenos:\n\n   import logging\n\n   log = logging.getLogger(__name__)\n\n   def log_callback(request):\n       \"\"\"Log information at the end of request\"\"\"\n       log.debug('Request is finished.')\n   request.add_finished_callback(log_callback)\n\nFinished callbacks are called in the order they're added\n(first-to-most-recently-added).  Finished callbacks (unlike a :term:`response\ncallback`) are *always* called, even if an exception happens in application\ncode that prevents a response from being generated.\n\nThe set of finished callbacks associated with a request are called *very late*\nin the processing of that request; they are essentially the very last thing\ncalled by the :term:`router` before a request \"ends\". They are called after\nresponse processing has already occurred in a top-level ``finally:`` block\nwithin the router request processing code.  As a result, mutations performed to\nthe ``request`` provided to a finished callback will have no meaningful effect,\nbecause response processing will have already occurred, and the request's scope\nwill expire almost immediately after all finished callbacks have been\nprocessed.\n\nErrors raised by finished callbacks are not handled specially.  They will be\npropagated to the caller of the :app:`Pyramid` router application.\n\nA finished callback has a lifetime of a *single* request.  If you want a\nfinished callback to happen as the result of *every* request, you must\nre-register the callback into every new request (perhaps within a subscriber of\na :class:`~pyramid.events.NewRequest` event).\n\n.. index::\n   single: traverser\n\n.. _changing_the_traverser:\n\nChanging the Traverser\n----------------------\n\nThe default :term:`traversal` algorithm that :app:`Pyramid` uses is explained\nin :ref:`traversal_algorithm`.  Though it is rarely necessary, this default\nalgorithm can be swapped out selectively for a different traversal pattern via\nconfiguration.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.config import Configurator\n   from myapp.traversal import Traverser\n   config = Configurator()\n   config.add_traverser(Traverser)\n\nIn the example above, ``myapp.traversal.Traverser`` is assumed to be a class\nthat implements the following interface:\n\n.. code-block:: python\n   :linenos:\n\n   class Traverser(object):\n       def __init__(self, root):\n           \"\"\" Accept the root object returned from the root factory \"\"\"\n\n       def __call__(self, request):\n           \"\"\" Return a dictionary with (at least) the keys ``root``,\n           ``context``, ``view_name``, ``subpath``, ``traversed``,\n           ``virtual_root``, and ``virtual_root_path``.  These values are\n           typically the result of a resource tree traversal.  ``root``\n           is the physical root object, ``context`` will be a resource\n           object, ``view_name`` will be the view name used (a Unicode\n           name), ``subpath`` will be a sequence of Unicode names that\n           followed the view name but were not traversed, ``traversed``\n           will be a sequence of Unicode names that were traversed\n           (including the virtual root path, if any) ``virtual_root``\n           will be a resource object representing the virtual root (or the\n           physical root if traversal was not performed), and\n           ``virtual_root_path`` will be a sequence representing the\n           virtual root path (a sequence of Unicode names) or None if\n           traversal was not performed.\n\n           Extra keys for special purpose functionality can be added as\n           necessary.\n\n           All values returned in the dictionary will be made available\n           as attributes of the ``request`` object.\n           \"\"\"\n\nMore than one traversal algorithm can be active at the same time.  For\ninstance, if your :term:`root factory` returns more than one type of object\nconditionally, you could claim that an alternative traverser adapter is \"for\"\nonly one particular class or interface.  When the root factory returned an\nobject that implemented that class or interface, a custom traverser would be\nused.  Otherwise the default traverser would be used.  For example:\n\n.. code-block:: python\n   :linenos:\n\n   from myapp.traversal import Traverser\n   from myapp.resources import MyRoot\n   from pyramid.config import Configurator\n   config = Configurator()\n   config.add_traverser(Traverser, MyRoot)\n\nIf the above stanza was added to a Pyramid ``__init__.py`` file's ``main``\nfunction, :app:`Pyramid` would use the ``myapp.traversal.Traverser`` only when\nthe application :term:`root factory` returned an instance of the\n``myapp.resources.MyRoot`` object.  Otherwise it would use the default\n:app:`Pyramid` traverser to do traversal.\n\n.. index::\n   single: URL generator\n\n.. _changing_resource_url:\n\nChanging How :meth:`pyramid.request.Request.resource_url` Generates a URL\n-------------------------------------------------------------------------\n\nWhen you add a traverser as described in :ref:`changing_the_traverser`, it's\noften convenient to continue to use the\n:meth:`pyramid.request.Request.resource_url` API.  However, since the way\ntraversal is done will have been modified, the URLs it generates by default may\nbe incorrect when used against resources derived from your custom traverser.\n\nIf you've added a traverser, you can change how\n:meth:`~pyramid.request.Request.resource_url` generates a URL for a specific\ntype of resource by adding a call to\n:meth:`pyramid.config.Configurator.add_resource_url_adapter`.\n\nFor example:\n\n.. code-block:: python\n   :linenos:\n\n   from myapp.traversal import ResourceURLAdapter\n   from myapp.resources import MyRoot\n\n   config.add_resource_url_adapter(ResourceURLAdapter, MyRoot)\n\nIn the above example, the ``myapp.traversal.ResourceURLAdapter`` class will be\nused to provide services to :meth:`~pyramid.request.Request.resource_url` any\ntime the :term:`resource` passed to ``resource_url`` is of the class\n``myapp.resources.MyRoot``.  The ``resource_iface`` argument ``MyRoot``\nrepresents the type of interface that must be possessed by the resource for\nthis resource url factory to be found.  If the ``resource_iface`` argument is\nomitted, this resource URL adapter will be used for *all* resources.\n\nThe API that must be implemented by a class that provides\n:class:`~pyramid.interfaces.IResourceURL` is as follows:\n\n.. code-block:: python\n  :linenos:\n\n  class MyResourceURL(object):\n      \"\"\" An adapter which provides the virtual and physical paths of a\n          resource\n      \"\"\"\n      def __init__(self, resource, request):\n          \"\"\" Accept the resource and request and set self.physical_path and\n          self.virtual_path \"\"\"\n          self.virtual_path =  some_function_of(resource, request)\n          self.physical_path =  some_other_function_of(resource, request)\n\nThe default context URL generator is available for perusal as the class\n:class:`pyramid.traversal.ResourceURL` in the `traversal module\n<https://github.com/Pylons/pyramid/blob/master/pyramid/traversal.py>`_ of the\n:term:`Pylons` GitHub Pyramid repository.\n\nSee :meth:`pyramid.config.Configurator.add_resource_url_adapter` for more\ninformation.\n\n.. index::\n   single: IResponse\n   single: special view responses\n\n.. _using_iresponse:\n\nChanging How Pyramid Treats View Responses\n------------------------------------------\n\n.. versionadded:: 1.1\n\nIt is possible to control how Pyramid treats the result of calling a view\ncallable on a per-type basis by using a hook involving\n:meth:`pyramid.config.Configurator.add_response_adapter` or the\n:class:`~pyramid.response.response_adapter` decorator.\n\nPyramid, in various places, adapts the result of calling a view callable to the\n:class:`~pyramid.interfaces.IResponse` interface to ensure that the object\nreturned by the view callable is a \"true\" response object.  The vast majority\nof time, the result of this adaptation is the result object itself, as view\ncallables written by \"civilians\" who read the narrative documentation contained\nin this manual will always return something that implements the\n:class:`~pyramid.interfaces.IResponse` interface.  Most typically, this will be\nan instance of the :class:`pyramid.response.Response` class or a subclass. If a\ncivilian returns a non-Response object from a view callable that isn't\nconfigured to use a :term:`renderer`, they will typically expect the router to\nraise an error.  However, you can hook Pyramid in such a way that users can\nreturn arbitrary values from a view callable by providing an adapter which\nconverts the arbitrary return value into something that implements\n:class:`~pyramid.interfaces.IResponse`.\n\nFor example, if you'd like to allow view callables to return bare string\nobjects (without requiring a :term:`renderer` to convert a string to a response\nobject), you can register an adapter which converts the string to a Response:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n\n   def string_response_adapter(s):\n       response = Response(s)\n       return response\n\n   # config is an instance of pyramid.config.Configurator\n\n   config.add_response_adapter(string_response_adapter, str)\n\nLikewise, if you want to be able to return a simplified kind of response object\nfrom view callables, you can use the IResponse hook to register an adapter to\nthe more complex IResponse interface:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n\n   class SimpleResponse(object):\n       def __init__(self, body):\n           self.body = body\n\n   def simple_response_adapter(simple_response):\n       response = Response(simple_response.body)\n       return response\n\n   # config is an instance of pyramid.config.Configurator\n\n   config.add_response_adapter(simple_response_adapter, SimpleResponse)\n\nIf you want to implement your own Response object instead of using the\n:class:`pyramid.response.Response` object in any capacity at all, you'll have\nto make sure that the object implements every attribute and method outlined in\n:class:`pyramid.interfaces.IResponse` and you'll have to ensure that it uses\n``zope.interface.implementer(IResponse)`` as a class decorator.\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.interfaces import IResponse\n   from zope.interface import implementer\n\n   @implementer(IResponse)\n   class MyResponse(object):\n       # ... an implementation of every method and attribute\n       # documented in IResponse should follow ...\n\nWhen an alternate response object implementation is returned by a view\ncallable, if that object asserts that it implements\n:class:`~pyramid.interfaces.IResponse` (via\n``zope.interface.implementer(IResponse)``) , an adapter needn't be registered\nfor the object; Pyramid will use it directly.\n\nAn IResponse adapter for ``webob.Response`` (as opposed to\n:class:`pyramid.response.Response`) is registered by Pyramid by default at\nstartup time, as by their nature, instances of this class (and instances of\nsubclasses of the class) will natively provide IResponse.  The adapter\nregistered for ``webob.Response`` simply returns the response object.\n\nInstead of using :meth:`pyramid.config.Configurator.add_response_adapter`, you\ncan use the :class:`pyramid.response.response_adapter` decorator:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n   from pyramid.response import response_adapter\n\n   @response_adapter(str)\n   def string_response_adapter(s):\n       response = Response(s)\n       return response\n\nThe above example, when scanned, has the same effect as:\n\n.. code-block:: python\n\n   config.add_response_adapter(string_response_adapter, str)\n\nThe :class:`~pyramid.response.response_adapter` decorator will have no effect\nuntil activated by a :term:`scan`.\n\n.. index::\n   single: view mapper\n\n.. _using_a_view_mapper:\n\nUsing a View Mapper\n-------------------\n\nThe default calling conventions for view callables are documented in the\n:ref:`views_chapter` chapter.  You can change the way users define view\ncallables by employing a :term:`view mapper`.\n\nA view mapper is an object that accepts a set of keyword arguments and which\nreturns a callable.  The returned callable is called with the :term:`view\ncallable` object.  The returned callable should itself return another callable\nwhich can be called with the \"internal calling protocol\" ``(context,\nrequest)``.\n\nYou can use a view mapper in a number of ways:\n\n- by setting a ``__view_mapper__`` attribute (which is the view mapper object)\n  on the view callable itself\n\n- by passing the mapper object to :meth:`pyramid.config.Configurator.add_view`\n  (or its declarative and decorator equivalents) as the ``mapper`` argument\n\n- by registering a *default* view mapper\n\nHere's an example of a view mapper that emulates (somewhat) a Pylons\n\"controller\".  The mapper is initialized with some keyword arguments.  Its\n``__call__`` method accepts the view object (which will be a class).  It uses\nthe ``attr`` keyword argument it is passed to determine which attribute should\nbe used as an action method.  The wrapper method it returns accepts ``(context,\nrequest)`` and returns the result of calling the action method with keyword\narguments implied by the :term:`matchdict` after popping the ``action`` out of\nit.  This somewhat emulates the Pylons style of calling action methods with\nrouting parameters pulled out of the route matching dict as keyword arguments.\n\n.. code-block:: python\n   :linenos:\n\n   # framework\n\n   class PylonsControllerViewMapper(object):\n       def __init__(self, **kw):\n           self.kw = kw\n\n       def __call__(self, view):\n           attr = self.kw['attr']\n           def wrapper(context, request):\n               matchdict = request.matchdict.copy()\n               matchdict.pop('action', None)\n               inst = view(request)\n               meth = getattr(inst, attr)\n               return meth(**matchdict)\n           return wrapper\n\n   class BaseController(object):\n       __view_mapper__ = PylonsControllerViewMapper\n\nA user might make use of these framework components like so:\n\n.. code-block:: python\n   :linenos:\n\n   # user application\n\n   from pyramid.response import Response\n   from pyramid.config import Configurator\n   import pyramid_handlers\n   from wsgiref.simple_server import make_server\n\n   class MyController(BaseController):\n       def index(self, id):\n           return Response(id)\n\n   if __name__ == '__main__':\n       config = Configurator()\n       config.include(pyramid_handlers)\n       config.add_handler('one', '/{id}', MyController, action='index')\n       config.add_handler('two', '/{action}/{id}', MyController)\n       server.make_server('0.0.0.0', 8080, config.make_wsgi_app())\n       server.serve_forever()\n\nThe :meth:`pyramid.config.Configurator.set_view_mapper` method can be used to\nset a *default* view mapper (overriding the superdefault view mapper used by\nPyramid itself).\n\nA *single* view registration can use a view mapper by passing the mapper as the\n``mapper`` argument to :meth:`~pyramid.config.Configurator.add_view`.\n\n.. index::\n   single: configuration decorator\n\n.. _registering_configuration_decorators:\n\nRegistering Configuration Decorators\n------------------------------------\n\nDecorators such as :class:`~pyramid.view.view_config` don't change the behavior\nof the functions or classes they're decorating.  Instead when a :term:`scan` is\nperformed, a modified version of the function or class is registered with\n:app:`Pyramid`.\n\nYou may wish to have your own decorators that offer such behaviour. This is\npossible by using the :term:`Venusian` package in the same way that it is used\nby :app:`Pyramid`.\n\nBy way of example, let's suppose you want to write a decorator that registers\nthe function it wraps with a :term:`Zope Component Architecture` \"utility\"\nwithin the :term:`application registry` provided by :app:`Pyramid`. The\napplication registry and the utility inside the registry is likely only to be\navailable once your application's configuration is at least partially\ncompleted. A normal decorator would fail as it would be executed before the\nconfiguration had even begun.\n\nHowever, using :term:`Venusian`, the decorator could be written as follows:\n\n.. code-block:: python\n   :linenos:\n\n   import venusian\n   from mypackage.interfaces import IMyUtility\n\n   class registerFunction(object):\n\n       def __init__(self, path):\n           self.path = path\n\n       def register(self, scanner, name, wrapped):\n           registry = scanner.config.registry\n           registry.getUtility(IMyUtility).register(\n               self.path, wrapped)\n\n       def __call__(self, wrapped):\n           venusian.attach(wrapped, self.register)\n           return wrapped\n\nThis decorator could then be used to register functions throughout your code:\n\n.. code-block:: python\n   :linenos:\n\n   @registerFunction('/some/path')\n   def my_function():\n       do_stuff()\n\nHowever, the utility would only be looked up when a :term:`scan` was performed,\nenabling you to set up the utility in advance:\n\n.. code-block:: python\n   :linenos:\n\n   from zope.interface import implementer\n\n   from wsgiref.simple_server import make_server\n   from pyramid.config import Configurator\n   from mypackage.interfaces import IMyUtility\n\n   @implementer(IMyUtility)\n   class UtilityImplementation:\n\n       def __init__(self):\n           self.registrations = {}\n\n       def register(self, path, callable_):\n           self.registrations[path] = callable_\n\n   if __name__ == '__main__':\n       config = Configurator()\n       config.registry.registerUtility(UtilityImplementation())\n       config.scan()\n       app = config.make_wsgi_app()\n       server = make_server('0.0.0.0', 8080, app)\n       server.serve_forever()\n\nFor full details, please read the `Venusian documentation\n<http://docs.repoze.org/venusian>`_.\n\n.. _registering_tweens:\n\nRegistering Tweens\n------------------\n\n.. versionadded:: 1.2\n   Tweens\n\nA :term:`tween` (a contraction of the word \"between\") is a bit of code that\nsits between the Pyramid router's main request handling function and the\nupstream WSGI component that uses :app:`Pyramid` as its \"app\".  This is a\nfeature that may be used by Pyramid framework extensions to provide, for\nexample, Pyramid-specific view timing support bookkeeping code that examines\nexceptions before they are returned to the upstream WSGI application.  Tweens\nbehave a bit like :term:`WSGI` :term:`middleware`, but they have the benefit of\nrunning in a context in which they have access to the Pyramid :term:`request`,\n:term:`response`, and :term:`application registry`, as well as the Pyramid\nrendering machinery.\n\nCreating a Tween\n~~~~~~~~~~~~~~~~\n\nTo create a tween, you must write a \"tween factory\".  A tween factory must be a\nglobally importable callable which accepts two arguments: ``handler`` and\n``registry``.  ``handler`` will be either the main Pyramid request handling\nfunction or another tween.  ``registry`` will be the Pyramid :term:`application\nregistry` represented by this Configurator.  A tween factory must return the\ntween (a callable object) when it is called.\n\nA tween is called with a single argument, ``request``, which is the\n:term:`request` created by Pyramid's router when it receives a WSGI request. A\ntween should return a :term:`response`, usually the one generated by the\ndownstream Pyramid application.\n\nYou can write the tween factory as a simple closure-returning function:\n\n.. code-block:: python\n    :linenos:\n\n    def simple_tween_factory(handler, registry):\n        # one-time configuration code goes here\n\n        def simple_tween(request):\n            # code to be executed for each request before\n            # the actual application code goes here\n\n            response = handler(request)\n\n            # code to be executed for each request after\n            # the actual application code goes here\n\n            return response\n\n        return simple_tween\n\nAlternatively, the tween factory can be a class with the ``__call__`` magic\nmethod:\n\n.. code-block:: python\n    :linenos:\n\n    class simple_tween_factory(object):\n        def __init__(self, handler, registry):\n            self.handler = handler\n            self.registry = registry\n\n            # one-time configuration code goes here\n\n        def __call__(self, request):\n            # code to be executed for each request before\n            # the actual application code goes here\n\n            response = self.handler(request)\n\n            # code to be executed for each request after\n            # the actual application code goes here\n\n            return response\n\nYou should avoid mutating any state on the tween instance. The tween is invoked\nonce per request and any shared mutable state needs to be carefully handled to\navoid any race conditions.\n\nThe closure style performs slightly better and enables you to conditionally\nomit the tween from the request processing pipeline (see the following timing\ntween example), whereas the class style makes it easier to have shared mutable\nstate and allows subclassing.\n\nHere's a complete example of a tween that logs the time spent processing each\nrequest:\n\n.. code-block:: python\n    :linenos:\n\n    # in a module named myapp.tweens\n\n    import time\n    from pyramid.settings import asbool\n    import logging\n\n    log = logging.getLogger(__name__)\n\n    def timing_tween_factory(handler, registry):\n        if asbool(registry.settings.get('do_timing')):\n            # if timing support is enabled, return a wrapper\n            def timing_tween(request):\n                start = time.time()\n                try:\n                    response = handler(request)\n                finally:\n                    end = time.time()\n                    log.debug('The request took %s seconds' %\n                              (end - start))\n                return response\n            return timing_tween\n        # if timing support is not enabled, return the original\n        # handler\n        return handler\n\nIn the above example, the tween factory defines a ``timing_tween`` tween and\nreturns it if ``asbool(registry.settings.get('do_timing'))`` is true.  It\notherwise simply returns the handler which it was given.  The\n``registry.settings`` attribute is a handle to the deployment settings provided\nby the user (usually in an ``.ini`` file).  In this case, if the user has\ndefined a ``do_timing`` setting and that setting is ``True``, the user has said\nthey want to do timing, so the tween factory returns the timing tween; it\notherwise just returns the handler it has been provided, preventing any timing.\n\nThe example timing tween simply records the start time, calls the downstream\nhandler, logs the number of seconds consumed by the downstream handler, and\nreturns the response.\n\nRegistering an Implicit Tween Factory\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce you've created a tween factory, you can register it into the implicit\ntween chain using the :meth:`pyramid.config.Configurator.add_tween` method\nusing its :term:`dotted Python name`.\n\nHere's an example of registering a tween factory as an \"implicit\" tween in a\nPyramid application:\n\n.. code-block:: python\n    :linenos:\n\n    from pyramid.config import Configurator\n    config = Configurator()\n    config.add_tween('myapp.tweens.timing_tween_factory')\n\nNote that you must use a :term:`dotted Python name` as the first argument to\n:meth:`pyramid.config.Configurator.add_tween`; this must point at a tween\nfactory.  You cannot pass the tween factory object itself to the method: it\nmust be :term:`dotted Python name` that points to a globally importable object.\nIn the above example, we assume that a ``timing_tween_factory`` tween factory\nwas defined in a module named ``myapp.tweens``, so the tween factory is\nimportable as ``myapp.tweens.timing_tween_factory``.\n\nWhen you use :meth:`pyramid.config.Configurator.add_tween`, you're instructing\nthe system to use your tween factory at startup time unless the user has\nprovided an explicit tween list in their configuration.  This is what's meant\nby an \"implicit\" tween.  A user can always elect to supply an explicit tween\nlist, reordering or disincluding implicitly added tweens.  See\n:ref:`explicit_tween_ordering` for more information about explicit tween\nordering.\n\nIf more than one call to :meth:`pyramid.config.Configurator.add_tween` is made\nwithin a single application configuration, the tweens will be chained together\nat application startup time.  The *first* tween factory added via ``add_tween``\nwill be called with the Pyramid exception view tween factory as its ``handler``\nargument, then the tween factory added directly after that one will be called\nwith the result of the first tween factory as its ``handler`` argument, and so\non, ad infinitum until all tween factories have been called. The Pyramid router\nwill use the outermost tween produced by this chain (the tween generated by the\nvery last tween factory added) as its request handler function.  For example:\n\n.. code-block:: python\n    :linenos:\n\n    from pyramid.config import Configurator\n\n    config = Configurator()\n    config.add_tween('myapp.tween_factory1')\n    config.add_tween('myapp.tween_factory2')\n\nThe above example will generate an implicit tween chain that looks like this::\n\n    INGRESS (implicit)\n    myapp.tween_factory2\n    myapp.tween_factory1\n    pyramid.tweens.excview_tween_factory (implicit)\n    MAIN (implicit)\n\nSuggesting Implicit Tween Ordering\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nBy default, as described above, the ordering of the chain is controlled\nentirely by the relative ordering of calls to\n:meth:`pyramid.config.Configurator.add_tween`.  However, the caller of\n``add_tween`` can provide an optional hint that can influence the implicit\ntween chain ordering by supplying ``under`` or ``over`` (or both) arguments to\n:meth:`~pyramid.config.Configurator.add_tween`.  These hints are only used when\nan explicit tween ordering is not used. See :ref:`explicit_tween_ordering` for\na description of how to set an explicit tween ordering.\n\nAllowable values for ``under`` or ``over`` (or both) are:\n\n- ``None`` (the default),\n\n- a :term:`dotted Python name` to a tween factory: a string representing the\n  predicted dotted name of a tween factory added in a call to ``add_tween`` in\n  the same configuration session,\n\n- one of the constants :attr:`pyramid.tweens.MAIN`,\n  :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`, or\n\n- an iterable of any combination of the above. This allows the user to specify\n  fallbacks if the desired tween is not included, as well as compatibility\n  with multiple other tweens.\n\nEffectively, ``over`` means \"closer to the request ingress than\" and ``under``\nmeans \"closer to the main Pyramid application than\". You can think of an onion\nwith outer layers over the inner layers, the application being under all the\nlayers at the center.\n\nFor example, the following call to\n:meth:`~pyramid.config.Configurator.add_tween` will attempt to place the tween\nfactory represented by ``myapp.tween_factory`` directly \"above\" (in ``ptweens``\norder) the main Pyramid request handler.\n\n.. code-block:: python\n   :linenos:\n\n   import pyramid.tweens\n\n   config.add_tween('myapp.tween_factory', over=pyramid.tweens.MAIN)\n\nThe above example will generate an implicit tween chain that looks like this::\n\n    INGRESS (implicit)\n    pyramid.tweens.excview_tween_factory (implicit)\n    myapp.tween_factory\n    MAIN (implicit)\n\nLikewise, calling the following call to\n:meth:`~pyramid.config.Configurator.add_tween` will attempt to place this tween\nfactory \"above\" the main handler but \"below\" a separately added tween factory:\n\n.. code-block:: python\n   :linenos:\n\n   import pyramid.tweens\n\n   config.add_tween('myapp.tween_factory1',\n                    over=pyramid.tweens.MAIN)\n   config.add_tween('myapp.tween_factory2',\n                    over=pyramid.tweens.MAIN,\n                    under='myapp.tween_factory1')\n\nThe above example will generate an implicit tween chain that looks like this::\n\n    INGRESS (implicit)\n    pyramid.tweens.excview_tween_factory (implicit)\n    myapp.tween_factory1\n    myapp.tween_factory2\n    MAIN (implicit)\n\nSpecifying neither ``over`` nor ``under`` is equivalent to specifying\n``under=INGRESS``.\n\nIf all options for ``under`` (or ``over``) cannot be found in the current\nconfiguration, it is an error. If some options are specified purely for\ncompatibilty with other tweens, just add a fallback of ``MAIN`` or ``INGRESS``.\nFor example, ``under=('someothertween', 'someothertween2', INGRESS)``. This\nconstraint will require the tween to be located under the ``someothertween``\ntween, the ``someothertween2`` tween, and ``INGRESS``. If any of these is not\nin the current configuration, this constraint will only organize itself based\non the tweens that are present.\n\n.. _explicit_tween_ordering:\n\nExplicit Tween Ordering\n~~~~~~~~~~~~~~~~~~~~~~~\n\nImplicit tween ordering is obviously only best-effort.  Pyramid will attempt to\nprovide an implicit order of tweens as best it can using hints provided by\ncalls to :meth:`~pyramid.config.Configurator.add_tween`.  But because it's only\nbest-effort, if very precise tween ordering is required, the only surefire way\nto get it is to use an explicit tween order.  The deploying user can override\nthe implicit tween inclusion and ordering implied by calls to\n:meth:`~pyramid.config.Configurator.add_tween` entirely by using the\n``pyramid.tweens`` settings value.  When used, this settings value must be a\nlist of Python dotted names which will override the ordering (and inclusion) of\ntween factories in the implicit tween chain.  For example:\n\n.. code-block:: ini\n   :linenos:\n\n   [app:main]\n   use = egg:MyApp\n   pyramid.reload_templates = true\n   pyramid.debug_authorization = false\n   pyramid.debug_notfound = false\n   pyramid.debug_routematch = false\n   pyramid.debug_templates = true\n   pyramid.tweens = myapp.my_cool_tween_factory\n                    pyramid.tweens.excview_tween_factory\n\nIn the above configuration, calls made during configuration to\n:meth:`pyramid.config.Configurator.add_tween` are ignored, and the user is\ntelling the system to use the tween factories he has listed in the\n``pyramid.tweens`` configuration setting (each is a :term:`dotted Python name`\nwhich points to a tween factory) instead of any tween factories added via\n:meth:`pyramid.config.Configurator.add_tween`.  The *first* tween factory in\nthe ``pyramid.tweens`` list will be used as the producer of the effective\n:app:`Pyramid` request handling function; it will wrap the tween factory\ndeclared directly \"below\" it, ad infinitum.  The \"main\" Pyramid request handler\nis implicit, and always \"at the bottom\".\n\n.. note::\n\n   Pyramid's own :term:`exception view` handling logic is implemented as a\n   tween factory function: :func:`pyramid.tweens.excview_tween_factory`.  If\n   Pyramid exception view handling is desired, and tween factories are\n   specified via the ``pyramid.tweens`` configuration setting, the\n   :func:`pyramid.tweens.excview_tween_factory` function must be added to the\n   ``pyramid.tweens`` configuration setting list explicitly.  If it is not\n   present, Pyramid will not perform exception view handling.\n\nTween Conflicts and Ordering Cycles\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nPyramid will prevent the same tween factory from being added to the tween chain\nmore than once using configuration conflict detection.  If you wish to add the\nsame tween factory more than once in a configuration, you should either: (a)\nuse a tween factory that is a separate globally importable instance object from\nthe factory that it conflicts with; (b) use a function or class as a tween\nfactory with the same logic as the other tween factory it conflicts with, but\nwith a different ``__name__`` attribute; or (c) call\n:meth:`pyramid.config.Configurator.commit` between calls to\n:meth:`pyramid.config.Configurator.add_tween`.\n\nIf a cycle is detected in implicit tween ordering when ``over`` and ``under``\nare used in any call to ``add_tween``, an exception will be raised at startup\ntime.\n\nDisplaying Tween Ordering\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe ``ptweens`` command-line utility can be used to report the current implict\nand explicit tween chains used by an application.  See\n:ref:`displaying_tweens`.\n\n.. _registering_thirdparty_predicates:\n\nAdding a Third Party View, Route, or Subscriber Predicate\n---------------------------------------------------------\n\n.. versionadded:: 1.4\n\n.. _view_and_route_predicates:\n\nView and Route Predicates\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nView and route predicates used during configuration allow you to narrow the set\nof circumstances under which a view or route will match.  For example, the\n``request_method`` view predicate can be used to ensure a view callable is only\ninvoked when the request's method is ``POST``:\n\n.. code-block:: python\n\n    @view_config(request_method='POST')\n    def someview(request):\n        ...\n\nLikewise, a similar predicate can be used as a *route* predicate:\n\n.. code-block:: python\n\n    config.add_route('name', '/foo', request_method='POST')\n\nMany other built-in predicates exists (``request_param``, and others).  You can\nadd third-party predicates to the list of available predicates by using one of\n:meth:`pyramid.config.Configurator.add_view_predicate` or\n:meth:`pyramid.config.Configurator.add_route_predicate`.  The former adds a\nview predicate, the latter a route predicate.\n\nWhen using one of those APIs, you pass a *name* and a *factory* to add a\npredicate during Pyramid's configuration stage.  For example:\n\n.. code-block:: python\n\n    config.add_view_predicate('content_type', ContentTypePredicate)\n\nThe above example adds a new predicate named ``content_type`` to the list of\navailable predicates for views.  This will allow the following view\nconfiguration statement to work:\n\n.. code-block:: python\n   :linenos:\n\n   @view_config(content_type='File')\n   def aview(request): ...\n\nThe first argument to :meth:`pyramid.config.Configurator.add_view_predicate`,\nthe name, is a string representing the name that is expected to be passed to\n``view_config`` (or its imperative analogue ``add_view``).\n\nThe second argument is a view or route predicate factory, or a :term:`dotted\nPython name` which refers to a view or route predicate factory.  A view or\nroute predicate factory is most often a class with a constructor\n(``__init__``), a ``text`` method, a ``phash`` method, and a ``__call__``\nmethod. For example:\n\n.. code-block:: python\n    :linenos:\n\n    class ContentTypePredicate(object):\n        def __init__(self, val, config):\n            self.val = val\n\n        def text(self):\n            return 'content_type = %s' % (self.val,)\n\n        phash = text\n\n        def __call__(self, context, request):\n            return getattr(context, 'content_type', None) == self.val\n\nThe constructor of a predicate factory takes two arguments: ``val`` and\n``config``.  The ``val`` argument will be the argument passed to\n``view_config`` (or ``add_view``).  In the example above, it will be the string\n``File``.  The second argument, ``config``, will be the Configurator instance\nat the time of configuration.\n\nThe ``text`` method must return a string.  It should be useful to describe the\nbehavior of the predicate in error messages.\n\nThe ``phash`` method must return a string or a sequence of strings.  It's most\noften the same as ``text``, as long as ``text`` uniquely describes the\npredicate's name and the value passed to the constructor.  If ``text`` is more\ngeneral, or doesn't describe things that way, ``phash`` should return a string\nwith the name and the value serialized.  The result of ``phash`` is not seen in\noutput anywhere, it just informs the uniqueness constraints for view\nconfiguration.\n\nThe ``__call__`` method of a predicate factory must accept a resource\n(``context``) and a request, and must return ``True`` or ``False``.  It is the\n\"meat\" of the predicate.\n\nYou can use the same predicate factory as both a view predicate and as a route\npredicate, but you'll need to call ``add_view_predicate`` and\n``add_route_predicate`` separately with the same factory.\n\n.. _subscriber_predicates:\n\nSubscriber Predicates\n~~~~~~~~~~~~~~~~~~~~~\n\nSubscriber predicates work almost exactly like view and route predicates. They\nnarrow the set of circumstances in which a subscriber will be called. There are\nseveral minor differences between a subscriber predicate and a view or route\npredicate:\n\n- There are no default subscriber predicates.  You must register one to use\n  one.\n\n- The ``__call__`` method of a subscriber predicate accepts a single ``event``\n  object instead of a ``context`` and a ``request``.\n\n- Not every subscriber predicate can be used with every event type.  Some\n  subscriber predicates will assume a certain event type.\n\nHere's an example of a subscriber predicate that can be used in conjunction\nwith a subscriber that subscribes to the :class:`pyramid.events.NewRequest`\nevent type.\n\n.. code-block:: python\n    :linenos:\n\n    class RequestPathStartsWith(object):\n        def __init__(self, val, config):\n            self.val = val\n\n        def text(self):\n            return 'path_startswith = %s' % (self.val,)\n\n        phash = text\n\n        def __call__(self, event):\n            return event.request.path.startswith(self.val)\n\nOnce you've created a subscriber predicate, it may registered via\n:meth:`pyramid.config.Configurator.add_subscriber_predicate`.  For example:\n\n.. code-block:: python\n\n    config.add_subscriber_predicate(\n        'request_path_startswith', RequestPathStartsWith)\n\nOnce a subscriber predicate is registered, you can use it in a call to\n:meth:`pyramid.config.Configurator.add_subscriber` or to\n:class:`pyramid.events.subscriber`.  Here's an example of using the previously\nregistered ``request_path_startswith`` predicate in a call to\n:meth:`~pyramid.config.Configurator.add_subscriber`:\n\n.. code-block:: python\n    :linenos:\n\n    # define a subscriber in your code\n\n    def yosubscriber(event):\n        event.request.yo = 'YO!'\n\n    # and at configuration time\n\n    config.add_subscriber(yosubscriber, NewRequest,\n           request_path_startswith='/add_yo')\n\nHere's the same subscriber/predicate/event-type combination used via\n:class:`~pyramid.events.subscriber`.\n\n.. code-block:: python\n    :linenos:\n\n    from pyramid.events import subscriber\n\n    @subscriber(NewRequest, request_path_startswith='/add_yo')\n    def yosubscriber(event):\n        event.request.yo = 'YO!'\n\nIn either of the above configurations, the ``yosubscriber`` callable will only\nbe called if the request path starts with ``/add_yo``.  Otherwise the event\nsubscriber will not be called.\n\nNote that the ``request_path_startswith`` subscriber you defined can be used\nwith events that have a ``request`` attribute, but not ones that do not.  So,\nfor example, the predicate can be used with subscribers registered for\n:class:`pyramid.events.NewRequest` and :class:`pyramid.events.ContextFound`\nevents, but it cannot be used with subscribers registered for\n:class:`pyramid.events.ApplicationCreated` because the latter type of event has\nno ``request`` attribute.  The point being, unlike route and view predicates,\nnot every type of subscriber predicate will necessarily be applicable for use\nin every subscriber registration.  It is not the responsibility of the\npredicate author to make every predicate make sense for every event type; it is\nthe responsibility of the predicate consumer to use predicates that make sense\nfor a particular event type registration.\n\n\n.. index::\n   single: view derivers\n\n.. _view_derivers:\n\nView Derivers\n-------------\n\n.. versionadded:: 1.7\n\nEvery URL processed by :app:`Pyramid` is matched against a custom view\npipeline. See :ref:`router_chapter` for how this works. The view pipeline\nitself is built from the user-supplied :term:`view callable`, which is then\ncomposed with :term:`view derivers <view deriver>`. A view deriver is a\ncomposable element of the view pipeline which is used to wrap a view with\nadded functionality. View derivers are very similar to the ``decorator``\nargument to :meth:`pyramid.config.Configurator.add_view`, except that they have\nthe option to execute for every view in the application.\n\nIt is helpful to think of a :term:`view deriver` as middleware for views.\nUnlike tweens or WSGI middleware which are scoped to the application itself,\na view deriver is invoked once per view in the application, and can use\nconfiguration options from the view to customize its behavior.\n\nBuilt-in View Derivers\n~~~~~~~~~~~~~~~~~~~~~~\n\nThere are several built-in view derivers that :app:`Pyramid` will automatically\napply to any view. Below they are defined in order from furthest to closest to\nthe user-defined :term:`view callable`:\n\n``secured_view``\n\n  Enforce the ``permission`` defined on the view. This element is a no-op if no\n  permission is defined. Note there will always be a permission defined if a\n  default permission was assigned via\n  :meth:`pyramid.config.Configurator.set_default_permission`.\n\n  This element will also output useful debugging information when\n  ``pyramid.debug_authorization`` is enabled.\n\n``owrapped_view``\n\n  Invokes the wrapped view defined by the ``wrapper`` option.\n\n``http_cached_view``\n\n  Applies cache control headers to the response defined by the ``http_cache``\n  option. This element is a no-op if the ``pyramid.prevent_http_cache`` setting\n  is enabled or the ``http_cache`` option is ``None``.\n\n``decorated_view``\n\n  Wraps the view with the decorators from the ``decorator`` option.\n\n``rendered_view``\n\n  Adapts the result of the :term:`view callable` into a :term:`response`\n  object. Below this point the result may be any Python object.\n\n``mapped_view``\n\n  Applies the :term:`view mapper` defined by the ``mapper`` option or the\n  application's default view mapper to the :term:`view callable`. This\n  is always the closest deriver to the user-defined view and standardizes the\n  view pipeline interface to accept ``(context, request)`` from all previous\n  view derivers.\n\n.. warning::\n\n   Any view derivers defined ``under`` the ``rendered_view`` are not\n   guaranteed to receive a valid response object. Rather they will receive the\n   result from the :term:`view mapper` which is likely the original response\n   returned from the view. This is possibly a dictionary for a renderer but it\n   may be any Python object that may be adapted into a response.\n\nCustom View Derivers\n~~~~~~~~~~~~~~~~~~~~\n\nIt is possible to define custom view derivers which will affect all views in an\napplication. There are many uses for this, but most will likely be centered\naround monitoring and security. In order to register a custom :term:`view\nderiver`, you should create a callable that conforms to the\n:class:`pyramid.interfaces.IViewDeriver` interface, and then register it with\nyour application using :meth:`pyramid.config.Configurator.add_view_deriver`.\nFor example, below is a callable that can provide timing information for the\nview pipeline:\n\n.. code-block:: python\n   :linenos:\n\n   import time\n\n   def timing_view(view, info):\n       def wrapper_view(context, request):\n           start = time.time()\n           response = view(context, request)\n           end = time.time()\n           response.headers['X-View-Performance'] = '%.3f' % (end - start,)\n       return wrapper_view\n\n   config.add_view_deriver(timing_view)\n\nView derivers are unique in that they have access to most of the options\npassed to :meth:`pyramid.config.Configurator.add_view` in order to decide what\nto do, and they have a chance to affect every view in the application.\n\nLet's look at one more example which will protect views by requiring a CSRF\ntoken unless ``disable_csrf=True`` is passed to the view:\n\n.. code-block:: python\n   :linenos:\n\n   from pyramid.response import Response\n   from pyramid.session import check_csrf_token\n\n   def require_csrf_view(view, info):\n       wrapper_view = view\n       if not info.options.get('disable_csrf', False):\n           def wrapper_view(context, request):\n               if request.method == 'POST':\n                   check_csrf_token(request)\n               return view(context, request)\n       return wrapper_view\n\n   require_csrf_view.options = ('disable_csrf',)\n\n   config.add_view_deriver(require_csrf_view)\n\n   def protected_view(request):\n       return Response('protected')\n\n   def unprotected_view(request):\n       return Response('unprotected')\n\n   config.add_view(protected_view, name='safe')\n   config.add_view(unprotected_view, name='unsafe', disable_csrf=True)\n\nNavigating to ``/safe`` with a POST request will then fail when the call to\n:func:`pyramid.session.check_csrf_token` raises a\n:class:`pyramid.exceptions.BadCSRFToken` exception. However, ``/unsafe`` will\nnot error.\n\nOrdering View Derivers\n~~~~~~~~~~~~~~~~~~~~~~\n\nBy default, every new view deriver is added between the ``decorated_view`` and\n``rendered_view`` built-in derivers. It is possible to customize this ordering\nusing the ``over`` and ``under`` options. Each option can use the names of\nother view derivers in order to specify an ordering. There should rarely be a\nreason to worry about the ordering of the derivers except when the deriver\ndepends on other operations in the view pipeline.\n\nBoth ``over`` and ``under`` may also be iterables of constraints. For either\noption, if one or more constraints was defined, at least one must be satisfied,\nelse a :class:`pyramid.exceptions.ConfigurationError` will be raised. This may\nbe used to define fallback constraints if another deriver is missing.\n\nTwo sentinel values exist, :attr:`pyramid.viewderivers.INGRESS` and\n:attr:`pyramid.viewderivers.VIEW`, which may be used when specifying\nconstraints at the edges of the view pipeline. For example, to add a deriver\nat the start of the pipeline you may use ``under=INGRESS``.\n\nIt is not possible to add a view deriver under the ``mapped_view`` as the\n:term:`view mapper` is intimately tied to the signature of the user-defined\n:term:`view callable`. If you simply need to know what the original view\ncallable was, it can be found as ``info.original_view`` on the provided\n:class:`pyramid.interfaces.IViewDeriverInfo` object passed to every view\nderiver.\n\n.. warning::\n\n   The default constraints for any view deriver are ``over='rendered_view'``\n   and ``under='decorated_view'``. When escaping these constraints you must\n   take care to avoid cyclic dependencies between derivers. For example, if\n   you want to add a new view deriver before ``secured_view`` then\n   simply specifying ``over='secured_view'`` is not enough, because the\n   default is also under ``decorated view`` there will be an unsatisfiable\n   cycle. You must specify a valid ``under`` constraint as well, such as\n   ``under=INGRESS`` to fall between INGRESS and ``secured_view`` at the\n   beginning of the view pipeline.\n",
            "header": {
                "file": {
                    "path": "docs/narr/hooks.rst"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "3a1ad8363",
                "new_commit_hash": "2c3782387",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/docs/narr/hooks.rst"
            },
            "plus_file": {
                "path": "b/docs/narr/hooks.rst"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1617,
                            "length": 6
                        },
                        "new_range": {
                            "start": 1617,
                            "length": 14
                        },
                        "section": "the user-defined :term:`view callable`:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "  view pipeline interface to accept ``(context, request)`` from all previous",
                                "type": "context"
                            },
                            {
                                "content": "  view derivers.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": ".. warning::",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "   Any view derivers defined ``under`` the ``rendered_view`` are not",
                                "type": "added"
                            },
                            {
                                "content": "   guaranteed to receive a valid response object. Rather they will receive the",
                                "type": "added"
                            },
                            {
                                "content": "   result from the :term:`view mapper` which is likely the original response",
                                "type": "added"
                            },
                            {
                                "content": "   returned from the view. This is possibly a dictionary for a renderer but it",
                                "type": "added"
                            },
                            {
                                "content": "   may be any Python object that may be adapted into a response.",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "Custom View Derivers",
                                "type": "context"
                            },
                            {
                                "content": "~~~~~~~~~~~~~~~~~~~~",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1642,
                            "length": 7
                        },
                        "new_range": {
                            "start": 1650,
                            "length": 7
                        },
                        "section": "view pipeline:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "           response.headers['X-View-Performance'] = '%.3f' % (end - start,)",
                                "type": "context"
                            },
                            {
                                "content": "       return wrapper_view",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "   config.add_view_deriver(timing_view, 'timing view')",
                                "type": "deleted"
                            },
                            {
                                "content": "   config.add_view_deriver(timing_view)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "View derivers are unique in that they have access to most of the options",
                                "type": "context"
                            },
                            {
                                "content": "passed to :meth:`pyramid.config.Configurator.add_view` in order to decide what",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1668,
                            "length": 7
                        },
                        "new_range": {
                            "start": 1676,
                            "length": 7
                        },
                        "section": "token unless ``disable_csrf=True`` is passed to the view:"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "   require_csrf_view.options = ('disable_csrf',)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "   config.add_view_deriver(require_csrf_view, 'require_csrf_view')",
                                "type": "deleted"
                            },
                            {
                                "content": "   config.add_view_deriver(require_csrf_view)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "   def protected_view(request):",
                                "type": "context"
                            },
                            {
                                "content": "       return Response('protected')",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1691,
                            "length": 13
                        },
                        "new_range": {
                            "start": 1699,
                            "length": 19
                        },
                        "section": "By default, every new view deriver is added between the ``decorated_view`` and"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "``rendered_view`` built-in derivers. It is possible to customize this ordering",
                                "type": "context"
                            },
                            {
                                "content": "using the ``over`` and ``under`` options. Each option can use the names of",
                                "type": "context"
                            },
                            {
                                "content": "other view derivers in order to specify an ordering. There should rarely be a",
                                "type": "context"
                            },
                            {
                                "content": "reason to worry about the ordering of the derivers.",
                                "type": "deleted"
                            },
                            {
                                "content": "reason to worry about the ordering of the derivers except when the deriver",
                                "type": "added"
                            },
                            {
                                "content": "depends on other operations in the view pipeline.",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "Both ``over`` and ``under`` may also be iterables of constraints. For either",
                                "type": "context"
                            },
                            {
                                "content": "option, if one or more constraints was defined, at least one must be satisfied,",
                                "type": "context"
                            },
                            {
                                "content": "else a :class:`pyramid.exceptions.ConfigurationError` will be raised. This may",
                                "type": "context"
                            },
                            {
                                "content": "be used to define fallback constraints if another deriver is missing.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "Two sentinel values exist, :attr:`pyramid.viewderivers.INGRESS` and",
                                "type": "added"
                            },
                            {
                                "content": ":attr:`pyramid.viewderivers.VIEW`, which may be used when specifying",
                                "type": "added"
                            },
                            {
                                "content": "constraints at the edges of the view pipeline. For example, to add a deriver",
                                "type": "added"
                            },
                            {
                                "content": "at the start of the pipeline you may use ``under=INGRESS``.",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "It is not possible to add a view deriver under the ``mapped_view`` as the",
                                "type": "context"
                            },
                            {
                                "content": ":term:`view mapper` is intimately tied to the signature of the user-defined",
                                "type": "context"
                            },
                            {
                                "content": ":term:`view callable`. If you simply need to know what the original view",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1707,
                            "length": 8
                        },
                        "new_range": {
                            "start": 1721,
                            "length": 12
                        },
                        "section": "deriver."
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": ".. warning::",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "   Any view derivers defined ``under`` the ``rendered_view`` are not",
                                "type": "deleted"
                            },
                            {
                                "content": "   guaranteed to receive a valid response object. Rather they will receive the",
                                "type": "deleted"
                            },
                            {
                                "content": "   result from the :term:`view mapper` which is likely the original response",
                                "type": "deleted"
                            },
                            {
                                "content": "   returned from the view. This is possibly a dictionary for a renderer but it",
                                "type": "deleted"
                            },
                            {
                                "content": "   may be any Python object that may be adapted into a response.",
                                "type": "deleted"
                            },
                            {
                                "content": "   The default constraints for any view deriver are ``over='rendered_view'``",
                                "type": "added"
                            },
                            {
                                "content": "   and ``under='decorated_view'``. When escaping these constraints you must",
                                "type": "added"
                            },
                            {
                                "content": "   take care to avoid cyclic dependencies between derivers. For example, if",
                                "type": "added"
                            },
                            {
                                "content": "   you want to add a new view deriver before ``secured_view`` then",
                                "type": "added"
                            },
                            {
                                "content": "   simply specifying ``over='secured_view'`` is not enough, because the",
                                "type": "added"
                            },
                            {
                                "content": "   default is also under ``decorated view`` there will be an unsatisfiable",
                                "type": "added"
                            },
                            {
                                "content": "   cycle. You must specify a valid ``under`` constraint as well, such as",
                                "type": "added"
                            },
                            {
                                "content": "   ``under=INGRESS`` to fall between INGRESS and ``secured_view`` at the",
                                "type": "added"
                            },
                            {
                                "content": "   beginning of the view pipeline.",
                                "type": "added"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import inspect\nimport posixpath\nimport operator\nimport os\nimport warnings\n\nfrom zope.interface import (\n    Interface,\n    implementedBy,\n    implementer,\n    )\n\nfrom zope.interface.interfaces import IInterface\n\nfrom pyramid.interfaces import (\n    IDefaultPermission,\n    IException,\n    IExceptionViewClassifier,\n    IMultiView,\n    IPackageOverrides,\n    IRendererFactory,\n    IRequest,\n    IResponse,\n    IRouteRequest,\n    ISecuredView,\n    IStaticURLInfo,\n    IView,\n    IViewClassifier,\n    IViewDerivers,\n    IViewDeriverInfo,\n    IViewMapperFactory,\n    PHASE1_CONFIG,\n    )\n\nfrom pyramid import renderers\n\nfrom pyramid.asset import resolve_asset_spec\nfrom pyramid.compat import (\n    string_types,\n    urlparse,\n    url_quote,\n    WIN,\n    is_nonstr_iter,\n    )\n\nfrom pyramid.decorator import reify\n\nfrom pyramid.exceptions import (\n    ConfigurationError,\n    PredicateMismatch,\n    )\n\nfrom pyramid.httpexceptions import (\n    HTTPForbidden,\n    HTTPNotFound,\n    default_exceptionresponse_view,\n    )\n\nfrom pyramid.registry import (\n    predvalseq,\n    Deferred,\n    )\n\nfrom pyramid.security import NO_PERMISSION_REQUIRED\nfrom pyramid.static import static_view\n\nfrom pyramid.url import parse_url_overrides\n\nfrom pyramid.view import AppendSlashNotFoundViewFactory\n\nimport pyramid.util\nfrom pyramid.util import (\n    viewdefaults,\n    action_method,\n    TopologicalSorter,\n    )\n\nimport pyramid.config.predicates\nimport pyramid.viewderivers\n\nfrom pyramid.viewderivers import (\n    INGRESS,\n    MAPPED_VIEW,\n    preserve_view_attrs,\n    view_description,\n    requestonly,\n    DefaultViewMapper,\n    wraps_view,\n)\n\nfrom pyramid.config.util import (\n    DEFAULT_PHASH,\n    MAX_ORDER,\n    as_sorted_tuple,\n    )\n\nurljoin = urlparse.urljoin\nurl_parse = urlparse.urlparse\n\nDefaultViewMapper = DefaultViewMapper # bw-compat\npreserve_view_attrs = preserve_view_attrs # bw-compat\nrequestonly = requestonly # bw-compat\nview_description = view_description # bw-compat\n\n@implementer(IMultiView)\nclass MultiView(object):\n\n    def __init__(self, name):\n        self.name = name\n        self.media_views = {}\n        self.views = []\n        self.accepts = []\n\n    def __discriminator__(self, context, request):\n        # used by introspection systems like so:\n        # view = adapters.lookup(....)\n        # view.__discriminator__(context, request) -> view's discriminator\n        # so that superdynamic systems can feed the discriminator to\n        # the introspection system to get info about it\n        view = self.match(context, request)\n        return view.__discriminator__(context, request)\n\n    def add(self, view, order, accept=None, phash=None):\n        if phash is not None:\n            for i, (s, v, h) in enumerate(list(self.views)):\n                if phash == h:\n                    self.views[i] = (order, view, phash)\n                    return\n\n        if accept is None or '*' in accept:\n            self.views.append((order, view, phash))\n            self.views.sort(key=operator.itemgetter(0))\n        else:\n            subset = self.media_views.setdefault(accept, [])\n            for i, (s, v, h) in enumerate(list(subset)):\n                if phash == h:\n                    subset[i] = (order, view, phash)\n                    return\n            else:\n                subset.append((order, view, phash))\n                subset.sort(key=operator.itemgetter(0))\n            accepts = set(self.accepts)\n            accepts.add(accept)\n            self.accepts = list(accepts) # dedupe\n\n    def get_views(self, request):\n        if self.accepts and hasattr(request, 'accept'):\n            accepts = self.accepts[:]\n            views = []\n            while accepts:\n                match = request.accept.best_match(accepts)\n                if match is None:\n                    break\n                subset = self.media_views[match]\n                views.extend(subset)\n                accepts.remove(match)\n            views.extend(self.views)\n            return views\n        return self.views\n\n    def match(self, context, request):\n        for order, view, phash in self.get_views(request):\n            if not hasattr(view, '__predicated__'):\n                return view\n            if view.__predicated__(context, request):\n                return view\n        raise PredicateMismatch(self.name)\n\n    def __permitted__(self, context, request):\n        view = self.match(context, request)\n        if hasattr(view, '__permitted__'):\n            return view.__permitted__(context, request)\n        return True\n\n    def __call_permissive__(self, context, request):\n        view = self.match(context, request)\n        view = getattr(view, '__call_permissive__', view)\n        return view(context, request)\n\n    def __call__(self, context, request):\n        for order, view, phash in self.get_views(request):\n            try:\n                return view(context, request)\n            except PredicateMismatch:\n                continue\n        raise PredicateMismatch(self.name)\n\nclass ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info\n\ndef isexception(o):\n    if IInterface.providedBy(o):\n        if IException.isEqualOrExtendedBy(o):\n            return True\n    return (\n        isinstance(o, Exception) or\n        (inspect.isclass(o) and (issubclass(o, Exception)))\n        )\n\n@implementer(IViewDeriverInfo)\nclass ViewDeriverInfo(object):\n    def __init__(self, view, registry, package, predicates, options):\n        self.original_view = view\n        self.registry = registry\n        self.package = package\n        self.predicates = predicates or []\n        self.options = options or {}\n\n    @reify\n    def settings(self):\n        return self.registry.settings\n\n@implementer(IStaticURLInfo)\nclass StaticURLInfo(object):\n    def __init__(self):\n        self.registrations = []\n        self.cache_busters = []\n\n    def generate(self, path, request, **kw):\n        for (url, spec, route_name) in self.registrations:\n            if path.startswith(spec):\n                subpath = path[len(spec):]\n                if WIN: # pragma: no cover\n                    subpath = subpath.replace('\\\\', '/') # windows\n                if self.cache_busters:\n                    subpath, kw = self._bust_asset_path(\n                        request, spec, subpath, kw)\n                if url is None:\n                    kw['subpath'] = subpath\n                    return request.route_url(route_name, **kw)\n                else:\n                    app_url, scheme, host, port, qs, anchor = \\\n                        parse_url_overrides(kw)\n                    parsed = url_parse(url)\n                    if not parsed.scheme:\n                        url = urlparse.urlunparse(parsed._replace(\n                            scheme=request.environ['wsgi.url_scheme']))\n                    subpath = url_quote(subpath)\n                    result = urljoin(url, subpath)\n                    return result + qs + anchor\n\n        raise ValueError('No static URL definition matching %s' % path)\n\n    def add(self, config, name, spec, **extra):\n        # This feature only allows for the serving of a directory and\n        # the files contained within, not of a single asset;\n        # appending a slash here if the spec doesn't have one is\n        # required for proper prefix matching done in ``generate``\n        # (``subpath = path[len(spec):]``).\n        if os.path.isabs(spec): # FBO windows\n            sep = os.sep\n        else:\n            sep = '/'\n        if not spec.endswith(sep) and not spec.endswith(':'):\n            spec = spec + sep\n\n        # we also make sure the name ends with a slash, purely as a\n        # convenience: a name that is a url is required to end in a\n        # slash, so that ``urljoin(name, subpath))`` will work above\n        # when the name is a URL, and it doesn't hurt things for it to\n        # have a name that ends in a slash if it's used as a route\n        # name instead of a URL.\n        if not name.endswith('/'):\n            # make sure it ends with a slash\n            name = name + '/'\n\n        if url_parse(name).netloc:\n            # it's a URL\n            # url, spec, route_name\n            url = name\n            route_name = None\n        else:\n            # it's a view name\n            url = None\n            cache_max_age = extra.pop('cache_max_age', None)\n\n            # create a view\n            view = static_view(spec, cache_max_age=cache_max_age,\n                               use_subpath=True)\n\n            # Mutate extra to allow factory, etc to be passed through here.\n            # Treat permission specially because we'd like to default to\n            # permissiveness (see docs of config.add_static_view).\n            permission = extra.pop('permission', None)\n            if permission is None:\n                permission = NO_PERMISSION_REQUIRED\n\n            context = extra.pop('context', None)\n            if context is None:\n                context = extra.pop('for_', None)\n\n            renderer = extra.pop('renderer', None)\n\n            # register a route using the computed view, permission, and\n            # pattern, plus any extras passed to us via add_static_view\n            pattern = \"%s*subpath\" % name # name already ends with slash\n            if config.route_prefix:\n                route_name = '__%s/%s' % (config.route_prefix, name)\n            else:\n                route_name = '__%s' % name\n            config.add_route(route_name, pattern, **extra)\n            config.add_view(\n                route_name=route_name,\n                view=view,\n                permission=permission,\n                context=context,\n                renderer=renderer,\n            )\n\n        def register():\n            registrations = self.registrations\n\n            names = [t[0] for t in registrations]\n\n            if name in names:\n                idx = names.index(name)\n                registrations.pop(idx)\n\n            # url, spec, route_name\n            registrations.append((url, spec, route_name))\n\n        intr = config.introspectable('static views',\n                                     name,\n                                     'static view for %r' % name,\n                                     'static view')\n        intr['name'] = name\n        intr['spec'] = spec\n\n        config.action(None, callable=register, introspectables=(intr,))\n\n    def add_cache_buster(self, config, spec, cachebust, explicit=False):\n        # ensure the spec always has a trailing slash as we only support\n        # adding cache busters to folders, not files\n        if os.path.isabs(spec): # FBO windows\n            sep = os.sep\n        else:\n            sep = '/'\n        if not spec.endswith(sep) and not spec.endswith(':'):\n            spec = spec + sep\n\n        def register():\n            if config.registry.settings.get('pyramid.prevent_cachebust'):\n                return\n\n            cache_busters = self.cache_busters\n\n            # find duplicate cache buster (old_idx)\n            # and insertion location (new_idx)\n            new_idx, old_idx = len(cache_busters), None\n            for idx, (spec_, cb_, explicit_) in enumerate(cache_busters):\n                # if we find an identical (spec, explicit) then use it\n                if spec == spec_ and explicit == explicit_:\n                    old_idx = new_idx = idx\n                    break\n\n                # past all explicit==False specs then add to the end\n                elif not explicit and explicit_:\n                    new_idx = idx\n                    break\n\n                # explicit matches and spec is shorter\n                elif explicit == explicit_ and len(spec) < len(spec_):\n                    new_idx = idx\n                    break\n\n            if old_idx is not None:\n                cache_busters.pop(old_idx)\n\n            cache_busters.insert(new_idx, (spec, cachebust, explicit))\n\n        intr = config.introspectable('cache busters',\n                                     spec,\n                                     'cache buster for %r' % spec,\n                                     'cache buster')\n        intr['cachebust'] = cachebust\n        intr['path'] = spec\n        intr['explicit'] = explicit\n\n        config.action(None, callable=register, introspectables=(intr,))\n\n    def _bust_asset_path(self, request, spec, subpath, kw):\n        registry = request.registry\n        pkg_name, pkg_subpath = resolve_asset_spec(spec)\n        rawspec = None\n\n        if pkg_name is not None:\n            pathspec = '{0}:{1}{2}'.format(pkg_name, pkg_subpath, subpath)\n            overrides = registry.queryUtility(IPackageOverrides, name=pkg_name)\n            if overrides is not None:\n                resource_name = posixpath.join(pkg_subpath, subpath)\n                sources = overrides.filtered_sources(resource_name)\n                for source, filtered_path in sources:\n                    rawspec = source.get_path(filtered_path)\n                    if hasattr(source, 'pkg_name'):\n                        rawspec = '{0}:{1}'.format(source.pkg_name, rawspec)\n                    break\n\n        else:\n            pathspec = pkg_subpath + subpath\n\n        if rawspec is None:\n            rawspec = pathspec\n\n        kw['pathspec'] = pathspec\n        kw['rawspec'] = rawspec\n        for spec_, cachebust, explicit in reversed(self.cache_busters):\n            if (\n                (explicit and rawspec.startswith(spec_)) or\n                (not explicit and pathspec.startswith(spec_))\n            ):\n                subpath, kw = cachebust(request, subpath, kw)\n                break\n        return subpath, kw\n",
            "new_file_content": "import inspect\nimport posixpath\nimport operator\nimport os\nimport warnings\n\nfrom zope.interface import (\n    Interface,\n    implementedBy,\n    implementer,\n    )\n\nfrom zope.interface.interfaces import IInterface\n\nfrom pyramid.interfaces import (\n    IDefaultPermission,\n    IException,\n    IExceptionViewClassifier,\n    IMultiView,\n    IPackageOverrides,\n    IRendererFactory,\n    IRequest,\n    IResponse,\n    IRouteRequest,\n    ISecuredView,\n    IStaticURLInfo,\n    IView,\n    IViewClassifier,\n    IViewDerivers,\n    IViewDeriverInfo,\n    IViewMapperFactory,\n    PHASE1_CONFIG,\n    )\n\nfrom pyramid import renderers\n\nfrom pyramid.asset import resolve_asset_spec\nfrom pyramid.compat import (\n    string_types,\n    urlparse,\n    url_quote,\n    WIN,\n    is_nonstr_iter,\n    )\n\nfrom pyramid.decorator import reify\n\nfrom pyramid.exceptions import (\n    ConfigurationError,\n    PredicateMismatch,\n    )\n\nfrom pyramid.httpexceptions import (\n    HTTPForbidden,\n    HTTPNotFound,\n    default_exceptionresponse_view,\n    )\n\nfrom pyramid.registry import (\n    predvalseq,\n    Deferred,\n    )\n\nfrom pyramid.security import NO_PERMISSION_REQUIRED\nfrom pyramid.static import static_view\n\nfrom pyramid.url import parse_url_overrides\n\nfrom pyramid.view import AppendSlashNotFoundViewFactory\n\nimport pyramid.util\nfrom pyramid.util import (\n    viewdefaults,\n    action_method,\n    TopologicalSorter,\n    )\n\nimport pyramid.config.predicates\nimport pyramid.viewderivers\n\nfrom pyramid.viewderivers import (\n    INGRESS,\n    VIEW,\n    preserve_view_attrs,\n    view_description,\n    requestonly,\n    DefaultViewMapper,\n    wraps_view,\n)\n\nfrom pyramid.config.util import (\n    DEFAULT_PHASH,\n    MAX_ORDER,\n    as_sorted_tuple,\n    )\n\nurljoin = urlparse.urljoin\nurl_parse = urlparse.urlparse\n\nDefaultViewMapper = DefaultViewMapper # bw-compat\npreserve_view_attrs = preserve_view_attrs # bw-compat\nrequestonly = requestonly # bw-compat\nview_description = view_description # bw-compat\n\n@implementer(IMultiView)\nclass MultiView(object):\n\n    def __init__(self, name):\n        self.name = name\n        self.media_views = {}\n        self.views = []\n        self.accepts = []\n\n    def __discriminator__(self, context, request):\n        # used by introspection systems like so:\n        # view = adapters.lookup(....)\n        # view.__discriminator__(context, request) -> view's discriminator\n        # so that superdynamic systems can feed the discriminator to\n        # the introspection system to get info about it\n        view = self.match(context, request)\n        return view.__discriminator__(context, request)\n\n    def add(self, view, order, accept=None, phash=None):\n        if phash is not None:\n            for i, (s, v, h) in enumerate(list(self.views)):\n                if phash == h:\n                    self.views[i] = (order, view, phash)\n                    return\n\n        if accept is None or '*' in accept:\n            self.views.append((order, view, phash))\n            self.views.sort(key=operator.itemgetter(0))\n        else:\n            subset = self.media_views.setdefault(accept, [])\n            for i, (s, v, h) in enumerate(list(subset)):\n                if phash == h:\n                    subset[i] = (order, view, phash)\n                    return\n            else:\n                subset.append((order, view, phash))\n                subset.sort(key=operator.itemgetter(0))\n            accepts = set(self.accepts)\n            accepts.add(accept)\n            self.accepts = list(accepts) # dedupe\n\n    def get_views(self, request):\n        if self.accepts and hasattr(request, 'accept'):\n            accepts = self.accepts[:]\n            views = []\n            while accepts:\n                match = request.accept.best_match(accepts)\n                if match is None:\n                    break\n                subset = self.media_views[match]\n                views.extend(subset)\n                accepts.remove(match)\n            views.extend(self.views)\n            return views\n        return self.views\n\n    def match(self, context, request):\n        for order, view, phash in self.get_views(request):\n            if not hasattr(view, '__predicated__'):\n                return view\n            if view.__predicated__(context, request):\n                return view\n        raise PredicateMismatch(self.name)\n\n    def __permitted__(self, context, request):\n        view = self.match(context, request)\n        if hasattr(view, '__permitted__'):\n            return view.__permitted__(context, request)\n        return True\n\n    def __call_permissive__(self, context, request):\n        view = self.match(context, request)\n        view = getattr(view, '__call_permissive__', view)\n        return view(context, request)\n\n    def __call__(self, context, request):\n        for order, view, phash in self.get_views(request):\n            try:\n                return view(context, request)\n            except PredicateMismatch:\n                continue\n        raise PredicateMismatch(self.name)\n\nclass ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        The default value for ``over`` is ``rendered_view`` and ``under`` is\n        ``decorated_view``. This places the deriver somewhere between the two\n        in the view pipeline. If the deriver should be placed elsewhere in the\n        pipeline, such as above ``decorated_view``, then you MUST also specify\n        ``under`` to something earlier in the order, or a\n        ``CyclicDependencyError`` will be raised when trying to sort the\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS, VIEW):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None:\n            under = 'decorated_view'\n\n        if over is None:\n            over = 'rendered_view'\n\n        over = as_sorted_tuple(over)\n        under = as_sorted_tuple(under)\n\n        if INGRESS in over:\n            raise ConfigurationError('%s cannot be over INGRESS' % name)\n\n        # ensure everything is always over mapped_view\n        if VIEW in over and name != 'mapped_view':\n            over = as_sorted_tuple(over + ('mapped_view',))\n\n        if VIEW in under:\n            raise ConfigurationError('%s cannot be under VIEW' % name)\n        if 'mapped_view' in under:\n            raise ConfigurationError('%s cannot be under \"mapped_view\"' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n            ('mapped_view', d.mapped_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=VIEW,\n            )\n            last = name\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info\n\ndef isexception(o):\n    if IInterface.providedBy(o):\n        if IException.isEqualOrExtendedBy(o):\n            return True\n    return (\n        isinstance(o, Exception) or\n        (inspect.isclass(o) and (issubclass(o, Exception)))\n        )\n\n@implementer(IViewDeriverInfo)\nclass ViewDeriverInfo(object):\n    def __init__(self, view, registry, package, predicates, options):\n        self.original_view = view\n        self.registry = registry\n        self.package = package\n        self.predicates = predicates or []\n        self.options = options or {}\n\n    @reify\n    def settings(self):\n        return self.registry.settings\n\n@implementer(IStaticURLInfo)\nclass StaticURLInfo(object):\n    def __init__(self):\n        self.registrations = []\n        self.cache_busters = []\n\n    def generate(self, path, request, **kw):\n        for (url, spec, route_name) in self.registrations:\n            if path.startswith(spec):\n                subpath = path[len(spec):]\n                if WIN: # pragma: no cover\n                    subpath = subpath.replace('\\\\', '/') # windows\n                if self.cache_busters:\n                    subpath, kw = self._bust_asset_path(\n                        request, spec, subpath, kw)\n                if url is None:\n                    kw['subpath'] = subpath\n                    return request.route_url(route_name, **kw)\n                else:\n                    app_url, scheme, host, port, qs, anchor = \\\n                        parse_url_overrides(kw)\n                    parsed = url_parse(url)\n                    if not parsed.scheme:\n                        url = urlparse.urlunparse(parsed._replace(\n                            scheme=request.environ['wsgi.url_scheme']))\n                    subpath = url_quote(subpath)\n                    result = urljoin(url, subpath)\n                    return result + qs + anchor\n\n        raise ValueError('No static URL definition matching %s' % path)\n\n    def add(self, config, name, spec, **extra):\n        # This feature only allows for the serving of a directory and\n        # the files contained within, not of a single asset;\n        # appending a slash here if the spec doesn't have one is\n        # required for proper prefix matching done in ``generate``\n        # (``subpath = path[len(spec):]``).\n        if os.path.isabs(spec): # FBO windows\n            sep = os.sep\n        else:\n            sep = '/'\n        if not spec.endswith(sep) and not spec.endswith(':'):\n            spec = spec + sep\n\n        # we also make sure the name ends with a slash, purely as a\n        # convenience: a name that is a url is required to end in a\n        # slash, so that ``urljoin(name, subpath))`` will work above\n        # when the name is a URL, and it doesn't hurt things for it to\n        # have a name that ends in a slash if it's used as a route\n        # name instead of a URL.\n        if not name.endswith('/'):\n            # make sure it ends with a slash\n            name = name + '/'\n\n        if url_parse(name).netloc:\n            # it's a URL\n            # url, spec, route_name\n            url = name\n            route_name = None\n        else:\n            # it's a view name\n            url = None\n            cache_max_age = extra.pop('cache_max_age', None)\n\n            # create a view\n            view = static_view(spec, cache_max_age=cache_max_age,\n                               use_subpath=True)\n\n            # Mutate extra to allow factory, etc to be passed through here.\n            # Treat permission specially because we'd like to default to\n            # permissiveness (see docs of config.add_static_view).\n            permission = extra.pop('permission', None)\n            if permission is None:\n                permission = NO_PERMISSION_REQUIRED\n\n            context = extra.pop('context', None)\n            if context is None:\n                context = extra.pop('for_', None)\n\n            renderer = extra.pop('renderer', None)\n\n            # register a route using the computed view, permission, and\n            # pattern, plus any extras passed to us via add_static_view\n            pattern = \"%s*subpath\" % name # name already ends with slash\n            if config.route_prefix:\n                route_name = '__%s/%s' % (config.route_prefix, name)\n            else:\n                route_name = '__%s' % name\n            config.add_route(route_name, pattern, **extra)\n            config.add_view(\n                route_name=route_name,\n                view=view,\n                permission=permission,\n                context=context,\n                renderer=renderer,\n            )\n\n        def register():\n            registrations = self.registrations\n\n            names = [t[0] for t in registrations]\n\n            if name in names:\n                idx = names.index(name)\n                registrations.pop(idx)\n\n            # url, spec, route_name\n            registrations.append((url, spec, route_name))\n\n        intr = config.introspectable('static views',\n                                     name,\n                                     'static view for %r' % name,\n                                     'static view')\n        intr['name'] = name\n        intr['spec'] = spec\n\n        config.action(None, callable=register, introspectables=(intr,))\n\n    def add_cache_buster(self, config, spec, cachebust, explicit=False):\n        # ensure the spec always has a trailing slash as we only support\n        # adding cache busters to folders, not files\n        if os.path.isabs(spec): # FBO windows\n            sep = os.sep\n        else:\n            sep = '/'\n        if not spec.endswith(sep) and not spec.endswith(':'):\n            spec = spec + sep\n\n        def register():\n            if config.registry.settings.get('pyramid.prevent_cachebust'):\n                return\n\n            cache_busters = self.cache_busters\n\n            # find duplicate cache buster (old_idx)\n            # and insertion location (new_idx)\n            new_idx, old_idx = len(cache_busters), None\n            for idx, (spec_, cb_, explicit_) in enumerate(cache_busters):\n                # if we find an identical (spec, explicit) then use it\n                if spec == spec_ and explicit == explicit_:\n                    old_idx = new_idx = idx\n                    break\n\n                # past all explicit==False specs then add to the end\n                elif not explicit and explicit_:\n                    new_idx = idx\n                    break\n\n                # explicit matches and spec is shorter\n                elif explicit == explicit_ and len(spec) < len(spec_):\n                    new_idx = idx\n                    break\n\n            if old_idx is not None:\n                cache_busters.pop(old_idx)\n\n            cache_busters.insert(new_idx, (spec, cachebust, explicit))\n\n        intr = config.introspectable('cache busters',\n                                     spec,\n                                     'cache buster for %r' % spec,\n                                     'cache buster')\n        intr['cachebust'] = cachebust\n        intr['path'] = spec\n        intr['explicit'] = explicit\n\n        config.action(None, callable=register, introspectables=(intr,))\n\n    def _bust_asset_path(self, request, spec, subpath, kw):\n        registry = request.registry\n        pkg_name, pkg_subpath = resolve_asset_spec(spec)\n        rawspec = None\n\n        if pkg_name is not None:\n            pathspec = '{0}:{1}{2}'.format(pkg_name, pkg_subpath, subpath)\n            overrides = registry.queryUtility(IPackageOverrides, name=pkg_name)\n            if overrides is not None:\n                resource_name = posixpath.join(pkg_subpath, subpath)\n                sources = overrides.filtered_sources(resource_name)\n                for source, filtered_path in sources:\n                    rawspec = source.get_path(filtered_path)\n                    if hasattr(source, 'pkg_name'):\n                        rawspec = '{0}:{1}'.format(source.pkg_name, rawspec)\n                    break\n\n        else:\n            pathspec = pkg_subpath + subpath\n\n        if rawspec is None:\n            rawspec = pathspec\n\n        kw['pathspec'] = pathspec\n        kw['rawspec'] = rawspec\n        for spec_, cachebust, explicit in reversed(self.cache_busters):\n            if (\n                (explicit and rawspec.startswith(spec_)) or\n                (not explicit and pathspec.startswith(spec_))\n            ):\n                subpath, kw = cachebust(request, subpath, kw)\n                break\n        return subpath, kw\n",
            "header": {
                "file": {
                    "path": "pyramid/config/views.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "1e161177b",
                "new_commit_hash": "3f6a9080d",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/pyramid/config/views.py"
            },
            "plus_file": {
                "path": "b/pyramid/config/views.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 80,
                            "length": 7
                        },
                        "new_range": {
                            "start": 80,
                            "length": 7
                        },
                        "section": "import pyramid.viewderivers"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "from pyramid.viewderivers import (",
                                "type": "context"
                            },
                            {
                                "content": "    INGRESS,",
                                "type": "context"
                            },
                            {
                                "content": "    MAPPED_VIEW,",
                                "type": "deleted"
                            },
                            {
                                "content": "    VIEW,",
                                "type": "added"
                            },
                            {
                                "content": "    preserve_view_attrs,",
                                "type": "context"
                            },
                            {
                                "content": "    view_description,",
                                "type": "context"
                            },
                            {
                                "content": "    requestonly,",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "statement",
                            "name": "",
                            "content": "from pyramid.viewderivers import (\n    INGRESS,\n    VIEW,\n    preserve_view_attrs,\n    view_description,\n    requestonly,\n    DefaultViewMapper,\n    wraps_view,\n)",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 81,
                            "end_lineno": 89,
                            "parent": null
                        }
                    ],
                    "deleted_entities": [
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "statement",
                            "name": "",
                            "content": "from pyramid.viewderivers import (\n    INGRESS,\n    MAPPED_VIEW,\n    preserve_view_attrs,\n    view_description,\n    requestonly,\n    DefaultViewMapper,\n    wraps_view,\n)",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 81,
                            "end_lineno": 89,
                            "parent": null
                        }
                    ]
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1115,
                            "length": 9
                        },
                        "new_range": {
                            "start": 1115,
                            "length": 12
                        },
                        "section": "class ViewsConfiguratorMixin(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        ``under`` means closer to the user-defined :term:`view callable`,",
                                "type": "context"
                            },
                            {
                                "content": "        and ``over`` means closer to view pipeline ingress.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        Specifying neither ``under`` nor ``over`` is equivalent to specifying",
                                "type": "deleted"
                            },
                            {
                                "content": "        ``over='rendered_view'`` and ``under='decorated_view'``, placing the",
                                "type": "deleted"
                            },
                            {
                                "content": "        deriver somewhere between the ``decorated_view`` and ``rendered_view``",
                                "type": "deleted"
                            },
                            {
                                "content": "        The default value for ``over`` is ``rendered_view`` and ``under`` is",
                                "type": "added"
                            },
                            {
                                "content": "        ``decorated_view``. This places the deriver somewhere between the two",
                                "type": "added"
                            },
                            {
                                "content": "        in the view pipeline. If the deriver should be placed elsewhere in the",
                                "type": "added"
                            },
                            {
                                "content": "        pipeline, such as above ``decorated_view``, then you MUST also specify",
                                "type": "added"
                            },
                            {
                                "content": "        ``under`` to something earlier in the order, or a",
                                "type": "added"
                            },
                            {
                                "content": "        ``CyclicDependencyError`` will be raised when trying to sort the",
                                "type": "added"
                            },
                            {
                                "content": "        derivers.",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        See :ref:`view_derivers` for more information.",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "method",
                            "name": "ViewsConfiguratorMixin.add_view_deriver",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1094,
                            "end_lineno": 1181,
                            "parent": {
                                "file_name": "pyramid/config/views.py",
                                "type": "class",
                                "name": "ViewsConfiguratorMixin",
                                "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 188,
                                "end_lineno": 1710,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "class",
                            "name": "ViewsConfiguratorMixin",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 188,
                            "end_lineno": 1710,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1128,
                            "length": 33
                        },
                        "new_range": {
                            "start": 1131,
                            "length": 30
                        },
                        "section": "class ViewsConfiguratorMixin(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        if name is None:",
                                "type": "context"
                            },
                            {
                                "content": "            name = deriver.__name__",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if name in (INGRESS,):",
                                "type": "deleted"
                            },
                            {
                                "content": "        if name in (INGRESS, VIEW):",
                                "type": "added"
                            },
                            {
                                "content": "            raise ConfigurationError('%s is a reserved view deriver name'",
                                "type": "context"
                            },
                            {
                                "content": "                                     % name)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if under is None and over is None:",
                                "type": "deleted"
                            },
                            {
                                "content": "        if under is None:",
                                "type": "added"
                            },
                            {
                                "content": "            under = 'decorated_view'",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        if over is None:",
                                "type": "added"
                            },
                            {
                                "content": "            over = 'rendered_view'",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if over is None and name != MAPPED_VIEW:",
                                "type": "deleted"
                            },
                            {
                                "content": "            raise ConfigurationError('must specify an \"over\" constraint for '",
                                "type": "deleted"
                            },
                            {
                                "content": "                                     'the %s view deriver' % name)",
                                "type": "deleted"
                            },
                            {
                                "content": "        elif over is not None:",
                                "type": "deleted"
                            },
                            {
                                "content": "            over = as_sorted_tuple(over)",
                                "type": "deleted"
                            },
                            {
                                "content": "        over = as_sorted_tuple(over)",
                                "type": "added"
                            },
                            {
                                "content": "        under = as_sorted_tuple(under)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if under is None:",
                                "type": "deleted"
                            },
                            {
                                "content": "            raise ConfigurationError('must specify an \"under\" constraint for '",
                                "type": "deleted"
                            },
                            {
                                "content": "                                     'the %s view deriver' % name)",
                                "type": "deleted"
                            },
                            {
                                "content": "        else:",
                                "type": "deleted"
                            },
                            {
                                "content": "            under = as_sorted_tuple(under)",
                                "type": "deleted"
                            },
                            {
                                "content": "        if INGRESS in over:",
                                "type": "added"
                            },
                            {
                                "content": "            raise ConfigurationError('%s cannot be over INGRESS' % name)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if over is not None and INGRESS in over:",
                                "type": "deleted"
                            },
                            {
                                "content": "            raise ConfigurationError('%s cannot be over view deriver INGRESS'",
                                "type": "deleted"
                            },
                            {
                                "content": "                                     % name)",
                                "type": "deleted"
                            },
                            {
                                "content": "        # ensure everything is always over mapped_view",
                                "type": "added"
                            },
                            {
                                "content": "        if VIEW in over and name != 'mapped_view':",
                                "type": "added"
                            },
                            {
                                "content": "            over = as_sorted_tuple(over + ('mapped_view',))",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if MAPPED_VIEW in under:",
                                "type": "deleted"
                            },
                            {
                                "content": "            raise ConfigurationError('%s cannot be under view deriver '",
                                "type": "deleted"
                            },
                            {
                                "content": "                                     'MAPPED_VIEW' % name)",
                                "type": "deleted"
                            },
                            {
                                "content": "        if VIEW in under:",
                                "type": "added"
                            },
                            {
                                "content": "            raise ConfigurationError('%s cannot be under VIEW' % name)",
                                "type": "added"
                            },
                            {
                                "content": "        if 'mapped_view' in under:",
                                "type": "added"
                            },
                            {
                                "content": "            raise ConfigurationError('%s cannot be under \"mapped_view\"' % name)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        discriminator = ('view deriver', name)",
                                "type": "context"
                            },
                            {
                                "content": "        intr = self.introspectable(",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "method",
                            "name": "ViewsConfiguratorMixin.add_view_deriver",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1094,
                            "end_lineno": 1181,
                            "parent": {
                                "file_name": "pyramid/config/views.py",
                                "type": "class",
                                "name": "ViewsConfiguratorMixin",
                                "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 188,
                                "end_lineno": 1710,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "class",
                            "name": "ViewsConfiguratorMixin",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 188,
                            "end_lineno": 1710,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1173,
                            "length": 7
                        },
                        "new_range": {
                            "start": 1173,
                            "length": 7
                        },
                        "section": "class ViewsConfiguratorMixin(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                    default_before=None,",
                                "type": "context"
                            },
                            {
                                "content": "                    default_after=INGRESS,",
                                "type": "context"
                            },
                            {
                                "content": "                    first=INGRESS,",
                                "type": "context"
                            },
                            {
                                "content": "                    last=MAPPED_VIEW,",
                                "type": "deleted"
                            },
                            {
                                "content": "                    last=VIEW,",
                                "type": "added"
                            },
                            {
                                "content": "                )",
                                "type": "context"
                            },
                            {
                                "content": "                self.registry.registerUtility(derivers, IViewDerivers)",
                                "type": "context"
                            },
                            {
                                "content": "            derivers.add(name, deriver, before=over, after=under)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "method",
                            "name": "ViewsConfiguratorMixin.add_view_deriver",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1094,
                            "end_lineno": 1181,
                            "parent": {
                                "file_name": "pyramid/config/views.py",
                                "type": "class",
                                "name": "ViewsConfiguratorMixin",
                                "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 188,
                                "end_lineno": 1710,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "class",
                            "name": "ViewsConfiguratorMixin",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 188,
                            "end_lineno": 1710,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1188,
                            "length": 6
                        },
                        "new_range": {
                            "start": 1188,
                            "length": 7
                        },
                        "section": "class ViewsConfiguratorMixin(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            ('http_cached_view', d.http_cached_view),",
                                "type": "context"
                            },
                            {
                                "content": "            ('decorated_view', d.decorated_view),",
                                "type": "context"
                            },
                            {
                                "content": "            ('rendered_view', d.rendered_view),",
                                "type": "context"
                            },
                            {
                                "content": "            ('mapped_view', d.mapped_view),",
                                "type": "added"
                            },
                            {
                                "content": "        ]",
                                "type": "context"
                            },
                            {
                                "content": "        last = INGRESS",
                                "type": "context"
                            },
                            {
                                "content": "        for name, deriver in derivers:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "class",
                            "name": "ViewsConfiguratorMixin",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        The default value for ``over`` is ``rendered_view`` and ``under`` is\n        ``decorated_view``. This places the deriver somewhere between the two\n        in the view pipeline. If the deriver should be placed elsewhere in the\n        pipeline, such as above ``decorated_view``, then you MUST also specify\n        ``under`` to something earlier in the order, or a\n        ``CyclicDependencyError`` will be raised when trying to sort the\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS, VIEW):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None:\n            under = 'decorated_view'\n\n        if over is None:\n            over = 'rendered_view'\n\n        over = as_sorted_tuple(over)\n        under = as_sorted_tuple(under)\n\n        if INGRESS in over:\n            raise ConfigurationError('%s cannot be over INGRESS' % name)\n\n        # ensure everything is always over mapped_view\n        if VIEW in over and name != 'mapped_view':\n            over = as_sorted_tuple(over + ('mapped_view',))\n\n        if VIEW in under:\n            raise ConfigurationError('%s cannot be under VIEW' % name)\n        if 'mapped_view' in under:\n            raise ConfigurationError('%s cannot be under \"mapped_view\"' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n            ('mapped_view', d.mapped_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=VIEW,\n            )\n            last = name\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 188,
                            "end_lineno": 1709,
                            "parent": null
                        },
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "method",
                            "name": "ViewsConfiguratorMixin.add_default_view_derivers",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        The default value for ``over`` is ``rendered_view`` and ``under`` is\n        ``decorated_view``. This places the deriver somewhere between the two\n        in the view pipeline. If the deriver should be placed elsewhere in the\n        pipeline, such as above ``decorated_view``, then you MUST also specify\n        ``under`` to something earlier in the order, or a\n        ``CyclicDependencyError`` will be raised when trying to sort the\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS, VIEW):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None:\n            under = 'decorated_view'\n\n        if over is None:\n            over = 'rendered_view'\n\n        over = as_sorted_tuple(over)\n        under = as_sorted_tuple(under)\n\n        if INGRESS in over:\n            raise ConfigurationError('%s cannot be over INGRESS' % name)\n\n        # ensure everything is always over mapped_view\n        if VIEW in over and name != 'mapped_view':\n            over = as_sorted_tuple(over + ('mapped_view',))\n\n        if VIEW in under:\n            raise ConfigurationError('%s cannot be under VIEW' % name)\n        if 'mapped_view' in under:\n            raise ConfigurationError('%s cannot be under \"mapped_view\"' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n            ('mapped_view', d.mapped_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=VIEW,\n            )\n            last = name\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1183,
                            "end_lineno": 1201,
                            "parent": {
                                "file_name": "pyramid/config/views.py",
                                "type": "class",
                                "name": "ViewsConfiguratorMixin",
                                "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        The default value for ``over`` is ``rendered_view`` and ``under`` is\n        ``decorated_view``. This places the deriver somewhere between the two\n        in the view pipeline. If the deriver should be placed elsewhere in the\n        pipeline, such as above ``decorated_view``, then you MUST also specify\n        ``under`` to something earlier in the order, or a\n        ``CyclicDependencyError`` will be raised when trying to sort the\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS, VIEW):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None:\n            under = 'decorated_view'\n\n        if over is None:\n            over = 'rendered_view'\n\n        over = as_sorted_tuple(over)\n        under = as_sorted_tuple(under)\n\n        if INGRESS in over:\n            raise ConfigurationError('%s cannot be over INGRESS' % name)\n\n        # ensure everything is always over mapped_view\n        if VIEW in over and name != 'mapped_view':\n            over = as_sorted_tuple(over + ('mapped_view',))\n\n        if VIEW in under:\n            raise ConfigurationError('%s cannot be under VIEW' % name)\n        if 'mapped_view' in under:\n            raise ConfigurationError('%s cannot be under \"mapped_view\"' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n            ('mapped_view', d.mapped_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=VIEW,\n            )\n            last = name\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 188,
                                "end_lineno": 1709,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1195,
                            "length": 12
                        },
                        "new_range": {
                            "start": 1196,
                            "length": 10
                        },
                        "section": "class ViewsConfiguratorMixin(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                deriver,",
                                "type": "context"
                            },
                            {
                                "content": "                name=name,",
                                "type": "context"
                            },
                            {
                                "content": "                under=last,",
                                "type": "context"
                            },
                            {
                                "content": "                over=MAPPED_VIEW,",
                                "type": "deleted"
                            },
                            {
                                "content": "                over=VIEW,",
                                "type": "added"
                            },
                            {
                                "content": "            )",
                                "type": "context"
                            },
                            {
                                "content": "            last = name",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "    def derive_view(self, view, attr=None, renderer=None):",
                                "type": "context"
                            },
                            {
                                "content": "        \"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "        Create a :term:`view callable` using the function, instance,",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "class",
                            "name": "ViewsConfiguratorMixin",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 188,
                            "end_lineno": 1710,
                            "parent": null
                        },
                        {
                            "file_name": "pyramid/config/views.py",
                            "type": "method",
                            "name": "ViewsConfiguratorMixin.add_default_view_derivers",
                            "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1183,
                            "end_lineno": 1202,
                            "parent": {
                                "file_name": "pyramid/config/views.py",
                                "type": "class",
                                "name": "ViewsConfiguratorMixin",
                                "content": "class ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 188,
                                "end_lineno": 1710,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import unittest\nfrom zope.interface import implementer\n\nfrom pyramid import testing\nfrom pyramid.exceptions import ConfigurationError\nfrom pyramid.interfaces import (\n    IResponse,\n    IRequest,\n    )\n\nclass TestDeriveView(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def _makeRequest(self):\n        request = DummyRequest()\n        request.registry = self.config.registry\n        return request\n\n    def _registerLogger(self):\n        from pyramid.interfaces import IDebugLogger\n        logger = DummyLogger()\n        self.config.registry.registerUtility(logger, IDebugLogger)\n        return logger\n\n    def _registerSecurityPolicy(self, permissive):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(permissive)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n\n    def test_function_returns_non_adaptable(self):\n        def view(request):\n            return None\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable function '\n                'pyramid.tests.test_viewderivers.view into a response '\n                'object. The value returned was None. You may have forgotten '\n                'to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_function_returns_non_adaptable_dict(self):\n        def view(request):\n            return {'a':1}\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                \"Could not convert return value of the view callable function \"\n                \"pyramid.tests.test_viewderivers.view into a response \"\n                \"object. The value returned was {'a': 1}. You may have \"\n                \"forgotten to define a renderer in the view configuration.\"\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_instance_returns_non_adaptable(self):\n        class AView(object):\n            def __call__(self, request):\n                return None\n        view = AView()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            msg = e.args[0]\n            self.assertTrue(msg.startswith(\n                'Could not convert return value of the view callable object '\n                '<pyramid.tests.test_viewderivers.'))\n            self.assertTrue(msg.endswith(\n                '> into a response object. The value returned was None. You '\n                'may have forgotten to return a value from the view callable.'))\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_function_returns_true_Response_no_renderer(self):\n        from pyramid.response import Response\n        r = Response('Hello')\n        def view(request):\n            return r\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        response = result(None, None)\n        self.assertEqual(response, r)\n\n    def test_function_returns_true_Response_with_renderer(self):\n        from pyramid.response import Response\n        r = Response('Hello')\n        def view(request):\n            return r\n        renderer = object()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        response = result(None, None)\n        self.assertEqual(response, r)\n\n    def test_requestonly_default_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return None\n        result = self.config.derive_view(AView)\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method __call__ of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_requestonly_nondefault_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def theviewmethod(self):\n                return None\n        result = self.config.derive_view(AView, attr='theviewmethod')\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method theviewmethod of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_requestonly_function(self):\n        response = DummyResponse()\n        def view(request):\n            return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_requestonly_function_with_renderer(self):\n        response = DummyResponse()\n        class moo(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, 'OK')\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        def view(request):\n            return 'OK'\n        result = self.config.derive_view(view, renderer=moo())\n        self.assertFalse(result.__wraps__ is view)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_requestonly_function_with_renderer_request_override(self):\n        def moo(info):\n            def inner(value, system):\n                self.assertEqual(value, 'OK')\n                self.assertEqual(system['request'], request)\n                self.assertEqual(system['context'], context)\n                return b'moo'\n            return inner\n        def view(request):\n            return 'OK'\n        self.config.add_renderer('moo', moo)\n        result = self.config.derive_view(view, renderer='string')\n        self.assertFalse(result is view)\n        request = self._makeRequest()\n        request.override_renderer = 'moo'\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request).body, b'moo')\n\n    def test_requestonly_function_with_renderer_request_has_view(self):\n        response = DummyResponse()\n        class moo(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, 'OK')\n                self.assertEqual(view_inst, 'view')\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        def view(request):\n            return 'OK'\n        result = self.config.derive_view(view, renderer=moo())\n        self.assertFalse(result.__wraps__ is view)\n        request = self._makeRequest()\n        request.__view__ = 'view'\n        context = testing.DummyResource()\n        r = result(context, request)\n        self.assertEqual(r, response)\n        self.assertFalse(hasattr(request, '__view__'))\n\n    def test_class_without_attr(self):\n        response = DummyResponse()\n        class View(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(View)\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, View)\n\n    def test_class_with_attr(self):\n        response = DummyResponse()\n        class View(object):\n            def __init__(self, request):\n                pass\n            def another(self):\n                return response\n        result = self.config.derive_view(View, attr='another')\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, View)\n\n    def test_as_function_context_and_request(self):\n        def view(context, request):\n            return 'OK'\n        result = self.config.derive_view(view)\n        self.assertTrue(result.__wraps__ is view)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(view(None, None), 'OK')\n\n    def test_as_function_requestonly(self):\n        response = DummyResponse()\n        def view(request):\n            return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_as_newstyle_class_context_and_request(self):\n        response = DummyResponse()\n        class view(object):\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_newstyle_class_requestonly(self):\n        response = DummyResponse()\n        class view(object):\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_oldstyle_class_context_and_request(self):\n        response = DummyResponse()\n        class view:\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_oldstyle_class_requestonly(self):\n        response = DummyResponse()\n        class view:\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_instance_context_and_request(self):\n        response = DummyResponse()\n        class View:\n            def __call__(self, context, request):\n                return response\n        view = View()\n        result = self.config.derive_view(view)\n        self.assertTrue(result.__wraps__ is view)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_as_instance_requestonly(self):\n        response = DummyResponse()\n        class View:\n            def __call__(self, request):\n                return response\n        view = View()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertTrue('test_viewderivers' in result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_with_debug_authorization_no_authpol(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_authn_policy_no_authz_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(debug_authorization=True)\n        from pyramid.interfaces import IAuthenticationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_authz_policy_no_authn_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(debug_authorization=True)\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_no_permission(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        self._registerSecurityPolicy(True)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed (\"\n                         \"no permission registered)\")\n\n    def test_debug_auth_permission_authpol_permitted(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(True)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): True\")\n\n    def test_debug_auth_permission_authpol_permitted_no_request(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(True)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        self.assertEqual(result(None, None), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url None (view name \"\n                         \"None against context None): True\")\n\n    def test_debug_auth_permission_authpol_denied(self):\n        from pyramid.httpexceptions import HTTPForbidden\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertRaises(HTTPForbidden, result, None, request)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): False\")\n\n    def test_debug_auth_permission_authpol_denied2(self):\n        view = lambda *arg: 'OK'\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        permitted = result.__permitted__(None, None)\n        self.assertEqual(permitted, False)\n\n    def test_debug_auth_permission_authpol_overridden(self):\n        from pyramid.security import NO_PERMISSION_REQUIRED\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission=NO_PERMISSION_REQUIRED)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): \"\n                         \"Allowed (NO_PERMISSION_REQUIRED)\")\n\n    def test_secured_view_authn_policy_no_authz_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        from pyramid.interfaces import IAuthenticationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n\n    def test_secured_view_authz_policy_no_authn_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n\n    def test_secured_view_raises_forbidden_no_name(self):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        from pyramid.httpexceptions import HTTPForbidden\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        try:\n            result(None, request)\n        except HTTPForbidden as e:\n            self.assertEqual(e.message,\n                             'Unauthorized: <lambda> failed permission check')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_secured_view_raises_forbidden_with_name(self):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        from pyramid.httpexceptions import HTTPForbidden\n        def myview(request): pass\n        self.config.registry.settings = {}\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(myview, permission='view')\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        try:\n            result(None, request)\n        except HTTPForbidden as e:\n            self.assertEqual(e.message,\n                             'Unauthorized: myview failed permission check')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_view_has_no_name(self):\n        from pyramid.exceptions import PredicateMismatch\n        response = DummyResponse()\n        view = lambda *arg: response\n        def predicate1(context, request):\n            return False\n        predicate1.text = lambda *arg: 'text'\n        result = self.config._derive_view(view, predicates=[predicate1])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view <lambda> (text)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_view_has_name(self):\n        from pyramid.exceptions import PredicateMismatch\n        def myview(request): pass\n        def predicate1(context, request):\n            return False\n        predicate1.text = lambda *arg: 'text'\n        result = self.config._derive_view(myview, predicates=[predicate1])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view myview (text)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_exception_has_text_in_detail(self):\n        from pyramid.exceptions import PredicateMismatch\n        def myview(request): pass\n        def predicate1(context, request):\n            return True\n        predicate1.text = lambda *arg: 'pred1'\n        def predicate2(context, request):\n            return False\n        predicate2.text = lambda *arg: 'pred2'\n        result = self.config._derive_view(myview, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view myview (pred2)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_with_predicates_all(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        def predicate2(context, request):\n            predicates.append(True)\n            return True\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        next = result(None, None)\n        self.assertEqual(next, response)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_predicates_checker(self):\n        view = lambda *arg: 'OK'\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        def predicate2(context, request):\n            predicates.append(True)\n            return True\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        next = result.__predicated__(None, None)\n        self.assertEqual(next, True)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_predicates_notall(self):\n        from pyramid.httpexceptions import HTTPNotFound\n        view = lambda *arg: 'OK'\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        predicate1.text = lambda *arg: 'text'\n        def predicate2(context, request):\n            predicates.append(True)\n            return False\n        predicate2.text = lambda *arg: 'text'\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        self.assertRaises(HTTPNotFound, result, None, None)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_wrapper_viewname(self):\n        from pyramid.response import Response\n        from pyramid.interfaces import IView\n        from pyramid.interfaces import IViewClassifier\n        inner_response = Response('OK')\n        def inner_view(context, request):\n            return inner_response\n        def outer_view(context, request):\n            self.assertEqual(request.wrapped_response, inner_response)\n            self.assertEqual(request.wrapped_body, inner_response.body)\n            self.assertEqual(request.wrapped_view.__original_view__,\n                             inner_view)\n            return Response(b'outer ' + request.wrapped_body)\n        self.config.registry.registerAdapter(\n            outer_view, (IViewClassifier, None, None), IView, 'owrap')\n        result = self.config._derive_view(inner_view, viewname='inner',\n                                wrapper_viewname='owrap')\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        response = result(None, request)\n        self.assertEqual(response.body, b'outer OK')\n\n    def test_with_wrapper_viewname_notfound(self):\n        from pyramid.response import Response\n        inner_response = Response('OK')\n        def inner_view(context, request):\n            return inner_response\n        wrapped = self.config._derive_view(inner_view, viewname='inner',\n                                wrapper_viewname='owrap')\n        request = self._makeRequest()\n        self.assertRaises(ValueError, wrapped, None, request)\n\n    def test_as_newstyle_class_context_and_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View(object):\n            def __init__(self, context, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config._derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_newstyle_class_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View(object):\n            def __init__(self, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_oldstyle_cls_context_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def __init__(self, context, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_oldstyle_cls_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def __init__(self, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_instance_context_and_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def index(self, context, request):\n                return {'a':'1'}\n        view = View()\n        result = self.config.derive_view(view, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is view)\n        self.assertEqual(result.__module__, view.__module__)\n        self.assertEqual(result.__doc__, view.__doc__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_instance_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def index(self, request):\n                return {'a':'1'}\n        view = View()\n        result = self.config.derive_view(view, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is view)\n        self.assertEqual(result.__module__, view.__module__)\n        self.assertEqual(result.__doc__, view.__doc__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_with_view_mapper_config_specified(self):\n        response = DummyResponse()\n        class mapper(object):\n            def __init__(self, **kw):\n                self.kw = kw\n            def __call__(self, view):\n                def wrapped(context, request):\n                    return response\n                return wrapped\n        def view(context, request): return 'NOTOK'\n        result = self.config._derive_view(view, mapper=mapper)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_with_view_mapper_view_specified(self):\n        from pyramid.response import Response\n        response = Response()\n        def mapper(**kw):\n            def inner(view):\n                def superinner(context, request):\n                    self.assertEqual(request, None)\n                    return response\n                return superinner\n            return inner\n        def view(context, request): return 'NOTOK'\n        view.__view_mapper__ = mapper\n        result = self.config.derive_view(view)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_with_view_mapper_default_mapper_specified(self):\n        from pyramid.response import Response\n        response = Response()\n        def mapper(**kw):\n            def inner(view):\n                def superinner(context, request):\n                    self.assertEqual(request, None)\n                    return  response\n                return superinner\n            return inner\n        self.config.set_view_mapper(mapper)\n        def view(context, request): return 'NOTOK'\n        result = self.config.derive_view(view)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_attr_wrapped_view_branching_default_phash(self):\n        from pyramid.config.util import DEFAULT_PHASH\n        def view(context, request): pass\n        result = self.config._derive_view(view, phash=DEFAULT_PHASH)\n        self.assertEqual(result.__wraps__, view)\n\n    def test_attr_wrapped_view_branching_nondefault_phash(self):\n        def view(context, request): pass\n        result = self.config._derive_view(view, phash='nondefault')\n        self.assertNotEqual(result, view)\n\n    def test_http_cached_view_integer(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600')\n\n    def test_http_cached_view_timedelta(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, \n            http_cache=datetime.timedelta(hours=1))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600')\n\n    def test_http_cached_view_tuple(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view,\n            http_cache=(3600, {'public':True}))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600, public')\n\n    def test_http_cached_view_tuple_seconds_None(self):\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view,\n            http_cache=(None, {'public':True}))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertEqual(headers['Cache-Control'], 'public')\n\n    def test_http_cached_view_prevent_auto_set(self):\n        from pyramid.response import Response\n        response = Response()\n        response.cache_control.prevent_auto = True\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response) # doesn't blow up\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertFalse('Cache-Control' in headers)\n\n    def test_http_cached_prevent_http_cache_in_settings(self):\n        self.config.registry.settings['prevent_http_cache'] = True\n        from pyramid.response import Response\n        response = Response()\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertFalse('Cache-Control' in headers)\n\n    def test_http_cached_view_bad_tuple(self):\n        def view(request): pass\n        self.assertRaises(ConfigurationError, self.config._derive_view, \n            view, http_cache=(None,))\n\n\nclass TestDerivationOrder(unittest.TestCase):\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_right_order_user_sorted(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1')\n        self.config.add_view_deriver(None, 'deriv2', 'decorated_view', 'deriv1')\n        self.config.add_view_deriver(None, 'deriv3', 'deriv2', 'deriv1')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv2',\n            'deriv3',\n            'deriv1',\n            'rendered_view',\n            'mapped_view',\n            ], dlist)\n\n    def test_right_order_implicit(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1')\n        self.config.add_view_deriver(None, 'deriv2')\n        self.config.add_view_deriver(None, 'deriv3')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv3',\n            'deriv2',\n            'deriv1',\n            'rendered_view',\n            'mapped_view',\n            ], dlist)\n\n    def test_right_order_under_rendered_view(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1', 'rendered_view', 'mapped_view')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'rendered_view',\n            'deriv1',\n            'mapped_view',\n            ], dlist)\n\n\n    def test_right_order_under_rendered_view_others(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1', 'rendered_view', 'mapped_view')\n        self.config.add_view_deriver(None, 'deriv2')\n        self.config.add_view_deriver(None, 'deriv3')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv3',\n            'deriv2',\n            'rendered_view',\n            'deriv1',\n            'mapped_view',\n            ], dlist)\n\n\nclass TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n\nclass TestDeriverIntegration(unittest.TestCase):\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def _getViewCallable(self, config, ctx_iface=None, request_iface=None,\n                         name=''):\n        from zope.interface import Interface\n        from pyramid.interfaces import IRequest\n        from pyramid.interfaces import IView\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import IExceptionViewClassifier\n        classifier = IViewClassifier\n        if ctx_iface is None:\n            ctx_iface = Interface\n        if request_iface is None:\n            request_iface = IRequest\n        return config.registry.adapters.lookup(\n            (classifier, request_iface, ctx_iface), IView, name=name,\n            default=None)\n\n    def _makeRequest(self, config):\n        request = DummyRequest()\n        request.registry = config.registry\n        return request\n\n    def test_view_options(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append(info.options['deriv1'])\n            return view\n        deriv1.options = ('deriv1',)\n\n        def deriv2(view, info):\n            response.deriv.append(info.options['deriv2'])\n            return view\n        deriv2.options = ('deriv2',)\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2')\n        self.config.add_view(view, deriv1='test1', deriv2='test2')\n\n        wrapper = self._getViewCallable(self.config)\n        request = self._makeRequest(self.config)\n        request.method = 'GET'\n        self.assertEqual(wrapper(None, request), response)\n        self.assertEqual(['test1', 'test2'], response.deriv)\n\n    def test_unexpected_view_options(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.assertRaises(\n            ConfigurationError,\n            lambda: self.config.add_view(lambda r: {}, deriv1='test1'))\n\n@implementer(IResponse)\nclass DummyResponse(object):\n    content_type = None\n    default_content_type = None\n    body = None\n\nclass DummyRequest:\n    subpath = ()\n    matchdict = None\n    request_iface  = IRequest\n\n    def __init__(self, environ=None):\n        if environ is None:\n            environ = {}\n        self.environ = environ\n        self.params = {}\n        self.cookies = {}\n        self.response = DummyResponse()\n\nclass DummyLogger:\n    def __init__(self):\n        self.messages = []\n    def info(self, msg):\n        self.messages.append(msg)\n    warn = info\n    debug = info\n\nclass DummySecurityPolicy:\n    def __init__(self, permitted=True):\n        self.permitted = permitted\n\n    def effective_principals(self, request):\n        return []\n\n    def permits(self, context, principals, permission):\n        return self.permitted\n\ndef parse_httpdate(s):\n    import datetime\n    # cannot use %Z, must use literal GMT; Jython honors timezone\n    # but CPython does not\n    return datetime.datetime.strptime(s, \"%a, %d %b %Y %H:%M:%S GMT\")\n\ndef assert_similar_datetime(one, two):\n    for attr in ('year', 'month', 'day', 'hour', 'minute'):\n        one_attr = getattr(one, attr)\n        two_attr = getattr(two, attr)\n        if not one_attr == two_attr: # pragma: no cover\n            raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr))\n",
            "new_file_content": "import unittest\nfrom zope.interface import implementer\n\nfrom pyramid import testing\nfrom pyramid.exceptions import ConfigurationError\nfrom pyramid.interfaces import (\n    IResponse,\n    IRequest,\n    )\n\nclass TestDeriveView(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def _makeRequest(self):\n        request = DummyRequest()\n        request.registry = self.config.registry\n        return request\n\n    def _registerLogger(self):\n        from pyramid.interfaces import IDebugLogger\n        logger = DummyLogger()\n        self.config.registry.registerUtility(logger, IDebugLogger)\n        return logger\n\n    def _registerSecurityPolicy(self, permissive):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(permissive)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n\n    def test_function_returns_non_adaptable(self):\n        def view(request):\n            return None\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable function '\n                'pyramid.tests.test_viewderivers.view into a response '\n                'object. The value returned was None. You may have forgotten '\n                'to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_function_returns_non_adaptable_dict(self):\n        def view(request):\n            return {'a':1}\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                \"Could not convert return value of the view callable function \"\n                \"pyramid.tests.test_viewderivers.view into a response \"\n                \"object. The value returned was {'a': 1}. You may have \"\n                \"forgotten to define a renderer in the view configuration.\"\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_instance_returns_non_adaptable(self):\n        class AView(object):\n            def __call__(self, request):\n                return None\n        view = AView()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            msg = e.args[0]\n            self.assertTrue(msg.startswith(\n                'Could not convert return value of the view callable object '\n                '<pyramid.tests.test_viewderivers.'))\n            self.assertTrue(msg.endswith(\n                '> into a response object. The value returned was None. You '\n                'may have forgotten to return a value from the view callable.'))\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_function_returns_true_Response_no_renderer(self):\n        from pyramid.response import Response\n        r = Response('Hello')\n        def view(request):\n            return r\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        response = result(None, None)\n        self.assertEqual(response, r)\n\n    def test_function_returns_true_Response_with_renderer(self):\n        from pyramid.response import Response\n        r = Response('Hello')\n        def view(request):\n            return r\n        renderer = object()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        response = result(None, None)\n        self.assertEqual(response, r)\n\n    def test_requestonly_default_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return None\n        result = self.config.derive_view(AView)\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method __call__ of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_requestonly_nondefault_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def theviewmethod(self):\n                return None\n        result = self.config.derive_view(AView, attr='theviewmethod')\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method theviewmethod of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_requestonly_function(self):\n        response = DummyResponse()\n        def view(request):\n            return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_requestonly_function_with_renderer(self):\n        response = DummyResponse()\n        class moo(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, 'OK')\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        def view(request):\n            return 'OK'\n        result = self.config.derive_view(view, renderer=moo())\n        self.assertFalse(result.__wraps__ is view)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_requestonly_function_with_renderer_request_override(self):\n        def moo(info):\n            def inner(value, system):\n                self.assertEqual(value, 'OK')\n                self.assertEqual(system['request'], request)\n                self.assertEqual(system['context'], context)\n                return b'moo'\n            return inner\n        def view(request):\n            return 'OK'\n        self.config.add_renderer('moo', moo)\n        result = self.config.derive_view(view, renderer='string')\n        self.assertFalse(result is view)\n        request = self._makeRequest()\n        request.override_renderer = 'moo'\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request).body, b'moo')\n\n    def test_requestonly_function_with_renderer_request_has_view(self):\n        response = DummyResponse()\n        class moo(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, 'OK')\n                self.assertEqual(view_inst, 'view')\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        def view(request):\n            return 'OK'\n        result = self.config.derive_view(view, renderer=moo())\n        self.assertFalse(result.__wraps__ is view)\n        request = self._makeRequest()\n        request.__view__ = 'view'\n        context = testing.DummyResource()\n        r = result(context, request)\n        self.assertEqual(r, response)\n        self.assertFalse(hasattr(request, '__view__'))\n\n    def test_class_without_attr(self):\n        response = DummyResponse()\n        class View(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(View)\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, View)\n\n    def test_class_with_attr(self):\n        response = DummyResponse()\n        class View(object):\n            def __init__(self, request):\n                pass\n            def another(self):\n                return response\n        result = self.config.derive_view(View, attr='another')\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, View)\n\n    def test_as_function_context_and_request(self):\n        def view(context, request):\n            return 'OK'\n        result = self.config.derive_view(view)\n        self.assertTrue(result.__wraps__ is view)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(view(None, None), 'OK')\n\n    def test_as_function_requestonly(self):\n        response = DummyResponse()\n        def view(request):\n            return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_as_newstyle_class_context_and_request(self):\n        response = DummyResponse()\n        class view(object):\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_newstyle_class_requestonly(self):\n        response = DummyResponse()\n        class view(object):\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_oldstyle_class_context_and_request(self):\n        response = DummyResponse()\n        class view:\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_oldstyle_class_requestonly(self):\n        response = DummyResponse()\n        class view:\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_instance_context_and_request(self):\n        response = DummyResponse()\n        class View:\n            def __call__(self, context, request):\n                return response\n        view = View()\n        result = self.config.derive_view(view)\n        self.assertTrue(result.__wraps__ is view)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_as_instance_requestonly(self):\n        response = DummyResponse()\n        class View:\n            def __call__(self, request):\n                return response\n        view = View()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertTrue('test_viewderivers' in result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_with_debug_authorization_no_authpol(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_authn_policy_no_authz_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(debug_authorization=True)\n        from pyramid.interfaces import IAuthenticationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_authz_policy_no_authn_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(debug_authorization=True)\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_no_permission(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        self._registerSecurityPolicy(True)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed (\"\n                         \"no permission registered)\")\n\n    def test_debug_auth_permission_authpol_permitted(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(True)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): True\")\n\n    def test_debug_auth_permission_authpol_permitted_no_request(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(True)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        self.assertEqual(result(None, None), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url None (view name \"\n                         \"None against context None): True\")\n\n    def test_debug_auth_permission_authpol_denied(self):\n        from pyramid.httpexceptions import HTTPForbidden\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertRaises(HTTPForbidden, result, None, request)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): False\")\n\n    def test_debug_auth_permission_authpol_denied2(self):\n        view = lambda *arg: 'OK'\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        permitted = result.__permitted__(None, None)\n        self.assertEqual(permitted, False)\n\n    def test_debug_auth_permission_authpol_overridden(self):\n        from pyramid.security import NO_PERMISSION_REQUIRED\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission=NO_PERMISSION_REQUIRED)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): \"\n                         \"Allowed (NO_PERMISSION_REQUIRED)\")\n\n    def test_secured_view_authn_policy_no_authz_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        from pyramid.interfaces import IAuthenticationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n\n    def test_secured_view_authz_policy_no_authn_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n\n    def test_secured_view_raises_forbidden_no_name(self):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        from pyramid.httpexceptions import HTTPForbidden\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        try:\n            result(None, request)\n        except HTTPForbidden as e:\n            self.assertEqual(e.message,\n                             'Unauthorized: <lambda> failed permission check')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_secured_view_raises_forbidden_with_name(self):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        from pyramid.httpexceptions import HTTPForbidden\n        def myview(request): pass\n        self.config.registry.settings = {}\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(myview, permission='view')\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        try:\n            result(None, request)\n        except HTTPForbidden as e:\n            self.assertEqual(e.message,\n                             'Unauthorized: myview failed permission check')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_view_has_no_name(self):\n        from pyramid.exceptions import PredicateMismatch\n        response = DummyResponse()\n        view = lambda *arg: response\n        def predicate1(context, request):\n            return False\n        predicate1.text = lambda *arg: 'text'\n        result = self.config._derive_view(view, predicates=[predicate1])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view <lambda> (text)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_view_has_name(self):\n        from pyramid.exceptions import PredicateMismatch\n        def myview(request): pass\n        def predicate1(context, request):\n            return False\n        predicate1.text = lambda *arg: 'text'\n        result = self.config._derive_view(myview, predicates=[predicate1])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view myview (text)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_exception_has_text_in_detail(self):\n        from pyramid.exceptions import PredicateMismatch\n        def myview(request): pass\n        def predicate1(context, request):\n            return True\n        predicate1.text = lambda *arg: 'pred1'\n        def predicate2(context, request):\n            return False\n        predicate2.text = lambda *arg: 'pred2'\n        result = self.config._derive_view(myview, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view myview (pred2)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_with_predicates_all(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        def predicate2(context, request):\n            predicates.append(True)\n            return True\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        next = result(None, None)\n        self.assertEqual(next, response)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_predicates_checker(self):\n        view = lambda *arg: 'OK'\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        def predicate2(context, request):\n            predicates.append(True)\n            return True\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        next = result.__predicated__(None, None)\n        self.assertEqual(next, True)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_predicates_notall(self):\n        from pyramid.httpexceptions import HTTPNotFound\n        view = lambda *arg: 'OK'\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        predicate1.text = lambda *arg: 'text'\n        def predicate2(context, request):\n            predicates.append(True)\n            return False\n        predicate2.text = lambda *arg: 'text'\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        self.assertRaises(HTTPNotFound, result, None, None)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_wrapper_viewname(self):\n        from pyramid.response import Response\n        from pyramid.interfaces import IView\n        from pyramid.interfaces import IViewClassifier\n        inner_response = Response('OK')\n        def inner_view(context, request):\n            return inner_response\n        def outer_view(context, request):\n            self.assertEqual(request.wrapped_response, inner_response)\n            self.assertEqual(request.wrapped_body, inner_response.body)\n            self.assertEqual(request.wrapped_view.__original_view__,\n                             inner_view)\n            return Response(b'outer ' + request.wrapped_body)\n        self.config.registry.registerAdapter(\n            outer_view, (IViewClassifier, None, None), IView, 'owrap')\n        result = self.config._derive_view(inner_view, viewname='inner',\n                                wrapper_viewname='owrap')\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        response = result(None, request)\n        self.assertEqual(response.body, b'outer OK')\n\n    def test_with_wrapper_viewname_notfound(self):\n        from pyramid.response import Response\n        inner_response = Response('OK')\n        def inner_view(context, request):\n            return inner_response\n        wrapped = self.config._derive_view(inner_view, viewname='inner',\n                                wrapper_viewname='owrap')\n        request = self._makeRequest()\n        self.assertRaises(ValueError, wrapped, None, request)\n\n    def test_as_newstyle_class_context_and_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View(object):\n            def __init__(self, context, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config._derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_newstyle_class_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View(object):\n            def __init__(self, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_oldstyle_cls_context_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def __init__(self, context, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_oldstyle_cls_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def __init__(self, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_instance_context_and_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def index(self, context, request):\n                return {'a':'1'}\n        view = View()\n        result = self.config.derive_view(view, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is view)\n        self.assertEqual(result.__module__, view.__module__)\n        self.assertEqual(result.__doc__, view.__doc__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_instance_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def index(self, request):\n                return {'a':'1'}\n        view = View()\n        result = self.config.derive_view(view, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is view)\n        self.assertEqual(result.__module__, view.__module__)\n        self.assertEqual(result.__doc__, view.__doc__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_with_view_mapper_config_specified(self):\n        response = DummyResponse()\n        class mapper(object):\n            def __init__(self, **kw):\n                self.kw = kw\n            def __call__(self, view):\n                def wrapped(context, request):\n                    return response\n                return wrapped\n        def view(context, request): return 'NOTOK'\n        result = self.config._derive_view(view, mapper=mapper)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_with_view_mapper_view_specified(self):\n        from pyramid.response import Response\n        response = Response()\n        def mapper(**kw):\n            def inner(view):\n                def superinner(context, request):\n                    self.assertEqual(request, None)\n                    return response\n                return superinner\n            return inner\n        def view(context, request): return 'NOTOK'\n        view.__view_mapper__ = mapper\n        result = self.config.derive_view(view)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_with_view_mapper_default_mapper_specified(self):\n        from pyramid.response import Response\n        response = Response()\n        def mapper(**kw):\n            def inner(view):\n                def superinner(context, request):\n                    self.assertEqual(request, None)\n                    return  response\n                return superinner\n            return inner\n        self.config.set_view_mapper(mapper)\n        def view(context, request): return 'NOTOK'\n        result = self.config.derive_view(view)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_attr_wrapped_view_branching_default_phash(self):\n        from pyramid.config.util import DEFAULT_PHASH\n        def view(context, request): pass\n        result = self.config._derive_view(view, phash=DEFAULT_PHASH)\n        self.assertEqual(result.__wraps__, view)\n\n    def test_attr_wrapped_view_branching_nondefault_phash(self):\n        def view(context, request): pass\n        result = self.config._derive_view(view, phash='nondefault')\n        self.assertNotEqual(result, view)\n\n    def test_http_cached_view_integer(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600')\n\n    def test_http_cached_view_timedelta(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, \n            http_cache=datetime.timedelta(hours=1))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600')\n\n    def test_http_cached_view_tuple(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view,\n            http_cache=(3600, {'public':True}))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600, public')\n\n    def test_http_cached_view_tuple_seconds_None(self):\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view,\n            http_cache=(None, {'public':True}))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertEqual(headers['Cache-Control'], 'public')\n\n    def test_http_cached_view_prevent_auto_set(self):\n        from pyramid.response import Response\n        response = Response()\n        response.cache_control.prevent_auto = True\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response) # doesn't blow up\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertFalse('Cache-Control' in headers)\n\n    def test_http_cached_prevent_http_cache_in_settings(self):\n        self.config.registry.settings['prevent_http_cache'] = True\n        from pyramid.response import Response\n        response = Response()\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertFalse('Cache-Control' in headers)\n\n    def test_http_cached_view_bad_tuple(self):\n        def view(request): pass\n        self.assertRaises(ConfigurationError, self.config._derive_view, \n            view, http_cache=(None,))\n\n\nclass TestDerivationOrder(unittest.TestCase):\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_right_order_user_sorted(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1')\n        self.config.add_view_deriver(None, 'deriv2', 'decorated_view', 'deriv1')\n        self.config.add_view_deriver(None, 'deriv3', 'deriv2', 'deriv1')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv2',\n            'deriv3',\n            'deriv1',\n            'rendered_view',\n            'mapped_view',\n            ], dlist)\n\n    def test_right_order_implicit(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1')\n        self.config.add_view_deriver(None, 'deriv2')\n        self.config.add_view_deriver(None, 'deriv3')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv3',\n            'deriv2',\n            'deriv1',\n            'rendered_view',\n            'mapped_view',\n            ], dlist)\n\n    def test_right_order_under_rendered_view(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1', 'rendered_view', 'mapped_view')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'rendered_view',\n            'deriv1',\n            'mapped_view',\n            ], dlist)\n\n\n    def test_right_order_under_rendered_view_others(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1', 'rendered_view', 'mapped_view')\n        self.config.add_view_deriver(None, 'deriv2')\n        self.config.add_view_deriver(None, 'deriv3')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv3',\n            'deriv2',\n            'rendered_view',\n            'deriv1',\n            'mapped_view',\n            ], dlist)\n\n\nclass TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_override_mapped_view(self):\n        from pyramid.viewderivers import VIEW\n        response = DummyResponse()\n        view = lambda *arg: response\n        flags = {}\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(flags.get('deriv1'))\n\n        flags.clear()\n        self.config.add_view_deriver(\n            deriv1, name='mapped_view', under='rendered_view', over=VIEW)\n        result = self.config._derive_view(view)\n        self.assertTrue(flags.get('deriv1'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import VIEW\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under=VIEW)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n\nclass TestDeriverIntegration(unittest.TestCase):\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def _getViewCallable(self, config, ctx_iface=None, request_iface=None,\n                         name=''):\n        from zope.interface import Interface\n        from pyramid.interfaces import IRequest\n        from pyramid.interfaces import IView\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import IExceptionViewClassifier\n        classifier = IViewClassifier\n        if ctx_iface is None:\n            ctx_iface = Interface\n        if request_iface is None:\n            request_iface = IRequest\n        return config.registry.adapters.lookup(\n            (classifier, request_iface, ctx_iface), IView, name=name,\n            default=None)\n\n    def _makeRequest(self, config):\n        request = DummyRequest()\n        request.registry = config.registry\n        return request\n\n    def test_view_options(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append(info.options['deriv1'])\n            return view\n        deriv1.options = ('deriv1',)\n\n        def deriv2(view, info):\n            response.deriv.append(info.options['deriv2'])\n            return view\n        deriv2.options = ('deriv2',)\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2')\n        self.config.add_view(view, deriv1='test1', deriv2='test2')\n\n        wrapper = self._getViewCallable(self.config)\n        request = self._makeRequest(self.config)\n        request.method = 'GET'\n        self.assertEqual(wrapper(None, request), response)\n        self.assertEqual(['test1', 'test2'], response.deriv)\n\n    def test_unexpected_view_options(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.assertRaises(\n            ConfigurationError,\n            lambda: self.config.add_view(lambda r: {}, deriv1='test1'))\n\n@implementer(IResponse)\nclass DummyResponse(object):\n    content_type = None\n    default_content_type = None\n    body = None\n\nclass DummyRequest:\n    subpath = ()\n    matchdict = None\n    request_iface  = IRequest\n\n    def __init__(self, environ=None):\n        if environ is None:\n            environ = {}\n        self.environ = environ\n        self.params = {}\n        self.cookies = {}\n        self.response = DummyResponse()\n\nclass DummyLogger:\n    def __init__(self):\n        self.messages = []\n    def info(self, msg):\n        self.messages.append(msg)\n    warn = info\n    debug = info\n\nclass DummySecurityPolicy:\n    def __init__(self, permitted=True):\n        self.permitted = permitted\n\n    def effective_principals(self, request):\n        return []\n\n    def permits(self, context, principals, permission):\n        return self.permitted\n\ndef parse_httpdate(s):\n    import datetime\n    # cannot use %Z, must use literal GMT; Jython honors timezone\n    # but CPython does not\n    return datetime.datetime.strptime(s, \"%a, %d %b %Y %H:%M:%S GMT\")\n\ndef assert_similar_datetime(one, two):\n    for attr in ('year', 'month', 'day', 'hour', 'minute'):\n        one_attr = getattr(one, attr)\n        two_attr = getattr(two, attr)\n        if not one_attr == two_attr: # pragma: no cover\n            raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr))\n",
            "header": {
                "file": {
                    "path": "pyramid/tests/test_viewderivers.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "dd142769b",
                "new_commit_hash": "1823beb4d",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/pyramid/tests/test_viewderivers.py"
            },
            "plus_file": {
                "path": "b/pyramid/tests/test_viewderivers.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1239,
                            "length": 6
                        },
                        "new_range": {
                            "start": 1239,
                            "length": 25
                        },
                        "section": "class TestAddDeriver(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertFalse(flags.get('deriv1'))",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertTrue(flags.get('deriv2'))",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_override_mapped_view(self):",
                                "type": "added"
                            },
                            {
                                "content": "        from pyramid.viewderivers import VIEW",
                                "type": "added"
                            },
                            {
                                "content": "        response = DummyResponse()",
                                "type": "added"
                            },
                            {
                                "content": "        view = lambda *arg: response",
                                "type": "added"
                            },
                            {
                                "content": "        flags = {}",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        def deriv1(view, info):",
                                "type": "added"
                            },
                            {
                                "content": "            flags['deriv1'] = True",
                                "type": "added"
                            },
                            {
                                "content": "            return view",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        result = self.config._derive_view(view)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertFalse(flags.get('deriv1'))",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        flags.clear()",
                                "type": "added"
                            },
                            {
                                "content": "        self.config.add_view_deriver(",
                                "type": "added"
                            },
                            {
                                "content": "            deriv1, name='mapped_view', under='rendered_view', over=VIEW)",
                                "type": "added"
                            },
                            {
                                "content": "        result = self.config._derive_view(view)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertTrue(flags.get('deriv1'))",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def test_add_multi_derivers_ordered(self):",
                                "type": "context"
                            },
                            {
                                "content": "        from pyramid.viewderivers import INGRESS",
                                "type": "context"
                            },
                            {
                                "content": "        response = DummyResponse()",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "class",
                            "name": "TestAddDeriver",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_override_mapped_view(self):\n        from pyramid.viewderivers import VIEW\n        response = DummyResponse()\n        view = lambda *arg: response\n        flags = {}\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(flags.get('deriv1'))\n\n        flags.clear()\n        self.config.add_view_deriver(\n            deriv1, name='mapped_view', under='rendered_view', over=VIEW)\n        result = self.config._derive_view(view)\n        self.assertTrue(flags.get('deriv1'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import VIEW\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under=VIEW)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1188,
                            "end_lineno": 1329,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "method",
                            "name": "TestAddDeriver.test_override_mapped_view",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_override_mapped_view(self):\n        from pyramid.viewderivers import VIEW\n        response = DummyResponse()\n        view = lambda *arg: response\n        flags = {}\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(flags.get('deriv1'))\n\n        flags.clear()\n        self.config.add_view_deriver(\n            deriv1, name='mapped_view', under='rendered_view', over=VIEW)\n        result = self.config._derive_view(view)\n        self.assertTrue(flags.get('deriv1'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import VIEW\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under=VIEW)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1242,
                            "end_lineno": 1259,
                            "parent": {
                                "file_name": "pyramid/tests/test_viewderivers.py",
                                "type": "class",
                                "name": "TestAddDeriver",
                                "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_override_mapped_view(self):\n        from pyramid.viewderivers import VIEW\n        response = DummyResponse()\n        view = lambda *arg: response\n        flags = {}\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(flags.get('deriv1'))\n\n        flags.clear()\n        self.config.add_view_deriver(\n            deriv1, name='mapped_view', under='rendered_view', over=VIEW)\n        result = self.config._derive_view(view)\n        self.assertTrue(flags.get('deriv1'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import VIEW\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under=VIEW)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 1188,
                                "end_lineno": 1329,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1277,
                            "length": 34
                        },
                        "new_range": {
                            "start": 1296,
                            "length": 25
                        },
                        "section": "class TestAddDeriver(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertRaises(",
                                "type": "context"
                            },
                            {
                                "content": "            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_add_deriver_enforces_over_is_defined(self):",
                                "type": "deleted"
                            },
                            {
                                "content": "        from pyramid.exceptions import ConfigurationError",
                                "type": "deleted"
                            },
                            {
                                "content": "        def deriv1(view, info): pass",
                                "type": "deleted"
                            },
                            {
                                "content": "        try:",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.config.add_view_deriver(deriv1, under='rendered_view')",
                                "type": "deleted"
                            },
                            {
                                "content": "        except ConfigurationError as ex:",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])",
                                "type": "deleted"
                            },
                            {
                                "content": "        else: # pragma: no cover",
                                "type": "deleted"
                            },
                            {
                                "content": "            raise AssertionError",
                                "type": "deleted"
                            },
                            {
                                "content": "",
                                "type": "deleted"
                            },
                            {
                                "content": "    def test_add_deriver_enforces_under_is_defined(self):",
                                "type": "deleted"
                            },
                            {
                                "content": "    def test_add_deriver_enforces_ingress_is_first(self):",
                                "type": "added"
                            },
                            {
                                "content": "        from pyramid.exceptions import ConfigurationError",
                                "type": "context"
                            },
                            {
                                "content": "        from pyramid.viewderivers import INGRESS",
                                "type": "added"
                            },
                            {
                                "content": "        def deriv1(view, info): pass",
                                "type": "context"
                            },
                            {
                                "content": "        try:",
                                "type": "context"
                            },
                            {
                                "content": "            self.config.add_view_deriver(deriv1, over='rendered_view')",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.config.add_view_deriver(deriv1, over=INGRESS)",
                                "type": "added"
                            },
                            {
                                "content": "        except ConfigurationError as ex:",
                                "type": "context"
                            },
                            {
                                "content": "            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.assertTrue('cannot be over INGRESS' in ex.args[0])",
                                "type": "added"
                            },
                            {
                                "content": "        else: # pragma: no cover",
                                "type": "context"
                            },
                            {
                                "content": "            raise AssertionError",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_add_deriver_enforces_ingress_is_first(self):",
                                "type": "deleted"
                            },
                            {
                                "content": "    def test_add_deriver_enforces_view_is_last(self):",
                                "type": "added"
                            },
                            {
                                "content": "        from pyramid.exceptions import ConfigurationError",
                                "type": "context"
                            },
                            {
                                "content": "        from pyramid.viewderivers import INGRESS",
                                "type": "deleted"
                            },
                            {
                                "content": "        from pyramid.viewderivers import VIEW",
                                "type": "added"
                            },
                            {
                                "content": "        def deriv1(view, info): pass",
                                "type": "context"
                            },
                            {
                                "content": "        try:",
                                "type": "context"
                            },
                            {
                                "content": "            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.config.add_view_deriver(deriv1, under=VIEW)",
                                "type": "added"
                            },
                            {
                                "content": "        except ConfigurationError as ex:",
                                "type": "context"
                            },
                            {
                                "content": "            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.assertTrue('cannot be under VIEW' in ex.args[0])",
                                "type": "added"
                            },
                            {
                                "content": "        else: # pragma: no cover",
                                "type": "context"
                            },
                            {
                                "content": "            raise AssertionError",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "class",
                            "name": "TestAddDeriver",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1188,
                            "end_lineno": 1320,
                            "parent": null
                        },
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "method",
                            "name": "TestAddDeriver.test_add_deriver_enforces_ingress_is_first",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1300,
                            "end_lineno": 1309,
                            "parent": {
                                "file_name": "pyramid/tests/test_viewderivers.py",
                                "type": "class",
                                "name": "TestAddDeriver",
                                "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 1188,
                                "end_lineno": 1320,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "method",
                            "name": "TestAddDeriver.test_add_deriver_enforces_view_is_last",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_override_mapped_view(self):\n        from pyramid.viewderivers import VIEW\n        response = DummyResponse()\n        view = lambda *arg: response\n        flags = {}\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(flags.get('deriv1'))\n\n        flags.clear()\n        self.config.add_view_deriver(\n            deriv1, name='mapped_view', under='rendered_view', over=VIEW)\n        result = self.config._derive_view(view)\n        self.assertTrue(flags.get('deriv1'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import VIEW\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under=VIEW)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1310,
                            "end_lineno": 1319,
                            "parent": {
                                "file_name": "pyramid/tests/test_viewderivers.py",
                                "type": "class",
                                "name": "TestAddDeriver",
                                "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_override_mapped_view(self):\n        from pyramid.viewderivers import VIEW\n        response = DummyResponse()\n        view = lambda *arg: response\n        flags = {}\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(flags.get('deriv1'))\n\n        flags.clear()\n        self.config.add_view_deriver(\n            deriv1, name='mapped_view', under='rendered_view', over=VIEW)\n        result = self.config._derive_view(view)\n        self.assertTrue(flags.get('deriv1'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import VIEW\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under=VIEW)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 1188,
                                "end_lineno": 1329,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": [
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "method",
                            "name": "TestAddDeriver.test_add_deriver_enforces_over_is_defined",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1280,
                            "end_lineno": 1288,
                            "parent": {
                                "file_name": "pyramid/tests/test_viewderivers.py",
                                "type": "class",
                                "name": "TestAddDeriver",
                                "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 1188,
                                "end_lineno": 1320,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "method",
                            "name": "TestAddDeriver.test_add_deriver_enforces_under_is_defined",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1290,
                            "end_lineno": 1298,
                            "parent": {
                                "file_name": "pyramid/tests/test_viewderivers.py",
                                "type": "class",
                                "name": "TestAddDeriver",
                                "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 1188,
                                "end_lineno": 1320,
                                "parent": null
                            }
                        }
                    ]
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1312,
                            "length": 10
                        },
                        "new_range": {
                            "start": 1322,
                            "length": 9
                        },
                        "section": "class TestAddDeriver(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        from pyramid.exceptions import ConfigurationError",
                                "type": "context"
                            },
                            {
                                "content": "        def deriv1(view, info): pass",
                                "type": "context"
                            },
                            {
                                "content": "        try:",
                                "type": "context"
                            },
                            {
                                "content": "            self.config.add_view_deriver(",
                                "type": "deleted"
                            },
                            {
                                "content": "                deriv1, 'deriv1', 'mapped_view', 'rendered_view')",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')",
                                "type": "added"
                            },
                            {
                                "content": "        except ConfigurationError as ex:",
                                "type": "context"
                            },
                            {
                                "content": "            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])",
                                "type": "deleted"
                            },
                            {
                                "content": "            self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])",
                                "type": "added"
                            },
                            {
                                "content": "        else: # pragma: no cover",
                                "type": "context"
                            },
                            {
                                "content": "            raise AssertionError",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "method",
                            "name": "TestAddDeriver.test_add_deriver_enforces_mapped_view_is_last",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1311,
                            "end_lineno": 1320,
                            "parent": {
                                "file_name": "pyramid/tests/test_viewderivers.py",
                                "type": "class",
                                "name": "TestAddDeriver",
                                "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 1188,
                                "end_lineno": 1320,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "pyramid/tests/test_viewderivers.py",
                            "type": "class",
                            "name": "TestAddDeriver",
                            "content": "class TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_over_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"over\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_under_is_defined(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over='rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('must specify an \"under\" constraint' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under='rendered_view', over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over view deriver INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(\n                deriv1, 'deriv1', 'mapped_view', 'rendered_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under view deriver MAPPED_VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 1188,
                            "end_lineno": 1320,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "import inspect\n\nfrom zope.interface import (\n    implementer,\n    provider,\n    )\n\nfrom pyramid.security import NO_PERMISSION_REQUIRED\nfrom pyramid.response import Response\n\nfrom pyramid.interfaces import (\n    IAuthenticationPolicy,\n    IAuthorizationPolicy,\n    IDebugLogger,\n    IResponse,\n    IViewMapper,\n    IViewMapperFactory,\n    )\n\nfrom pyramid.compat import (\n    is_bound_method,\n    is_unbound_method,\n    )\n\nfrom pyramid.config.util import (\n    DEFAULT_PHASH,\n    MAX_ORDER,\n    takes_one_arg,\n    )\n\nfrom pyramid.exceptions import (\n    ConfigurationError,\n    PredicateMismatch,\n    )\nfrom pyramid.httpexceptions import HTTPForbidden\nfrom pyramid.util import object_description\nfrom pyramid.view import render_view_to_response\nfrom pyramid import renderers\n\n\ndef view_description(view):\n    try:\n        return view.__text__\n    except AttributeError:\n        # custom view mappers might not add __text__\n        return object_description(view)\n\ndef requestonly(view, attr=None):\n    return takes_one_arg(view, attr=attr, argname='request')\n\n@implementer(IViewMapper)\n@provider(IViewMapperFactory)\nclass DefaultViewMapper(object):\n    def __init__(self, **kw):\n        self.attr = kw.get('attr')\n\n    def __call__(self, view):\n        if is_unbound_method(view) and self.attr is None:\n            raise ConfigurationError((\n                'Unbound method calls are not supported, please set the class '\n                'as your `view` and the method as your `attr`'\n            ))\n\n        if inspect.isclass(view):\n            view = self.map_class(view)\n        else:\n            view = self.map_nonclass(view)\n        return view\n\n    def map_class(self, view):\n        ronly = requestonly(view, self.attr)\n        if ronly:\n            mapped_view = self.map_class_requestonly(view)\n        else:\n            mapped_view = self.map_class_native(view)\n        mapped_view.__text__ = 'method %s of %s' % (\n            self.attr or '__call__', object_description(view))\n        return mapped_view\n\n    def map_nonclass(self, view):\n        # We do more work here than appears necessary to avoid wrapping the\n        # view unless it actually requires wrapping (to avoid function call\n        # overhead).\n        mapped_view = view\n        ronly = requestonly(view, self.attr)\n        if ronly:\n            mapped_view = self.map_nonclass_requestonly(view)\n        elif self.attr:\n            mapped_view = self.map_nonclass_attr(view)\n        if inspect.isroutine(mapped_view):\n            # This branch will be true if the view is a function or a method.\n            # We potentially mutate an unwrapped object here if it's a\n            # function.  We do this to avoid function call overhead of\n            # injecting another wrapper.  However, we must wrap if the\n            # function is a bound method because we can't set attributes on a\n            # bound method.\n            if is_bound_method(view):\n                _mapped_view = mapped_view\n                def mapped_view(context, request):\n                    return _mapped_view(context, request)\n            if self.attr is not None:\n                mapped_view.__text__ = 'attr %s of %s' % (\n                    self.attr, object_description(view))\n            else:\n                mapped_view.__text__ = object_description(view)\n        return mapped_view\n\n    def map_class_requestonly(self, view):\n        # its a class that has an __init__ which only accepts request\n        attr = self.attr\n        def _class_requestonly_view(context, request):\n            inst = view(request)\n            request.__view__ = inst\n            if attr is None:\n                response = inst()\n            else:\n                response = getattr(inst, attr)()\n            return response\n        return _class_requestonly_view\n\n    def map_class_native(self, view):\n        # its a class that has an __init__ which accepts both context and\n        # request\n        attr = self.attr\n        def _class_view(context, request):\n            inst = view(context, request)\n            request.__view__ = inst\n            if attr is None:\n                response = inst()\n            else:\n                response = getattr(inst, attr)()\n            return response\n        return _class_view\n\n    def map_nonclass_requestonly(self, view):\n        # its a function that has a __call__ which accepts only a single\n        # request argument\n        attr = self.attr\n        def _requestonly_view(context, request):\n            if attr is None:\n                response = view(request)\n            else:\n                response = getattr(view, attr)(request)\n            return response\n        return _requestonly_view\n\n    def map_nonclass_attr(self, view):\n        # its a function that has a __call__ which accepts both context and\n        # request, but still has an attr\n        def _attr_view(context, request):\n            response = getattr(view, self.attr)(context, request)\n            return response\n        return _attr_view\n\n\ndef wraps_view(wrapper):\n    def inner(view, info):\n        wrapper_view = wrapper(view, info)\n        return preserve_view_attrs(view, wrapper_view)\n    return inner\n\ndef preserve_view_attrs(view, wrapper):\n    if view is None:\n        return wrapper\n\n    if wrapper is view:\n        return view\n\n    original_view = getattr(view, '__original_view__', None)\n\n    if original_view is None:\n        original_view = view\n\n    wrapper.__wraps__ = view\n    wrapper.__original_view__ = original_view\n    wrapper.__module__ = view.__module__\n    wrapper.__doc__ = view.__doc__\n\n    try:\n        wrapper.__name__ = view.__name__\n    except AttributeError:\n        wrapper.__name__ = repr(view)\n\n    # attrs that may not exist on \"view\", but, if so, must be attached to\n    # \"wrapped view\"\n    for attr in ('__permitted__', '__call_permissive__', '__permission__',\n                 '__predicated__', '__predicates__', '__accept__',\n                 '__order__', '__text__'):\n        try:\n            setattr(wrapper, attr, getattr(view, attr))\n        except AttributeError:\n            pass\n\n    return wrapper\n\ndef mapped_view(view, info):\n    mapper = info.options.get('mapper')\n    if mapper is None:\n        mapper = getattr(view, '__view_mapper__', None)\n        if mapper is None:\n            mapper = info.registry.queryUtility(IViewMapperFactory)\n            if mapper is None:\n                mapper = DefaultViewMapper\n\n    mapped_view = mapper(**info.options)(view)\n    return mapped_view\n\nmapped_view.options = ('mapper', 'attr')\n\ndef owrapped_view(view, info):\n    wrapper_viewname = info.options.get('wrapper')\n    viewname = info.options.get('name')\n    if not wrapper_viewname:\n        return view\n    def _owrapped_view(context, request):\n        response = view(context, request)\n        request.wrapped_response = response\n        request.wrapped_body = response.body\n        request.wrapped_view = view\n        wrapped_response = render_view_to_response(context, request,\n                                                   wrapper_viewname)\n        if wrapped_response is None:\n            raise ValueError(\n                'No wrapper view named %r found when executing view '\n                'named %r' % (wrapper_viewname, viewname))\n        return wrapped_response\n    return _owrapped_view\n\nowrapped_view.options = ('name', 'wrapper')\n\ndef http_cached_view(view, info):\n    if info.settings.get('prevent_http_cache', False):\n        return view\n\n    seconds = info.options.get('http_cache')\n\n    if seconds is None:\n        return view\n\n    options = {}\n\n    if isinstance(seconds, (tuple, list)):\n        try:\n            seconds, options = seconds\n        except ValueError:\n            raise ConfigurationError(\n                'If http_cache parameter is a tuple or list, it must be '\n                'in the form (seconds, options); not %s' % (seconds,))\n\n    def wrapper(context, request):\n        response = view(context, request)\n        prevent_caching = getattr(response.cache_control, 'prevent_auto',\n                                  False)\n        if not prevent_caching:\n            response.cache_expires(seconds, **options)\n        return response\n\n    return wrapper\n\nhttp_cached_view.options = ('http_cache',)\n\ndef secured_view(view, info):\n    for wrapper in (_secured_view, _authdebug_view):\n        view = wraps_view(wrapper)(view, info)\n    return view\n\nsecured_view.options = ('permission',)\n\ndef _secured_view(view, info):\n    permission = info.options.get('permission')\n    if permission == NO_PERMISSION_REQUIRED:\n        # allow views registered within configurations that have a\n        # default permission to explicitly override the default\n        # permission, replacing it with no permission at all\n        permission = None\n\n    wrapped_view = view\n    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)\n    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)\n\n    if authn_policy and authz_policy and (permission is not None):\n        def _permitted(context, request):\n            principals = authn_policy.effective_principals(request)\n            return authz_policy.permits(context, principals, permission)\n        def _secured_view(context, request):\n            result = _permitted(context, request)\n            if result:\n                return view(context, request)\n            view_name = getattr(view, '__name__', view)\n            msg = getattr(\n                request, 'authdebug_message',\n                'Unauthorized: %s failed permission check' % view_name)\n            raise HTTPForbidden(msg, result=result)\n        _secured_view.__call_permissive__ = view\n        _secured_view.__permitted__ = _permitted\n        _secured_view.__permission__ = permission\n        wrapped_view = _secured_view\n\n    return wrapped_view\n\ndef _authdebug_view(view, info):\n    wrapped_view = view\n    settings = info.settings\n    permission = info.options.get('permission')\n    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)\n    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)\n    logger = info.registry.queryUtility(IDebugLogger)\n    if settings and settings.get('debug_authorization', False):\n        def _authdebug_view(context, request):\n            view_name = getattr(request, 'view_name', None)\n\n            if authn_policy and authz_policy:\n                if permission is NO_PERMISSION_REQUIRED:\n                    msg = 'Allowed (NO_PERMISSION_REQUIRED)'\n                elif permission is None:\n                    msg = 'Allowed (no permission registered)'\n                else:\n                    principals = authn_policy.effective_principals(request)\n                    msg = str(authz_policy.permits(\n                        context, principals, permission))\n            else:\n                msg = 'Allowed (no authorization policy in use)'\n\n            view_name = getattr(request, 'view_name', None)\n            url = getattr(request, 'url', None)\n            msg = ('debug_authorization of url %s (view name %r against '\n                   'context %r): %s' % (url, view_name, context, msg))\n            if logger:\n                logger.debug(msg)\n            if request is not None:\n                request.authdebug_message = msg\n            return view(context, request)\n\n        wrapped_view = _authdebug_view\n\n    return wrapped_view\n\ndef predicated_view(view, info):\n    preds = info.predicates\n    if not preds:\n        return view\n    def predicate_wrapper(context, request):\n        for predicate in preds:\n            if not predicate(context, request):\n                view_name = getattr(view, '__name__', view)\n                raise PredicateMismatch(\n                    'predicate mismatch for view %s (%s)' % (\n                        view_name, predicate.text()))\n        return view(context, request)\n    def checker(context, request):\n        return all((predicate(context, request) for predicate in\n                    preds))\n    predicate_wrapper.__predicated__ = checker\n    predicate_wrapper.__predicates__ = preds\n    return predicate_wrapper\n\ndef attr_wrapped_view(view, info):\n    accept, order, phash = (info.options.get('accept', None),\n                            getattr(info, 'order', MAX_ORDER),\n                            getattr(info, 'phash', DEFAULT_PHASH))\n    # this is a little silly but we don't want to decorate the original\n    # function with attributes that indicate accept, order, and phash,\n    # so we use a wrapper\n    if (\n        (accept is None) and\n        (order == MAX_ORDER) and\n        (phash == DEFAULT_PHASH)\n    ):\n        return view # defaults\n    def attr_view(context, request):\n        return view(context, request)\n    attr_view.__accept__ = accept\n    attr_view.__order__ = order\n    attr_view.__phash__ = phash\n    attr_view.__view_attr__ = info.options.get('attr')\n    attr_view.__permission__ = info.options.get('permission')\n    return attr_view\n\nattr_wrapped_view.options = ('accept', 'attr', 'permission')\n\ndef rendered_view(view, info):\n    # one way or another this wrapper must produce a Response (unless\n    # the renderer is a NullRendererHelper)\n    renderer = info.options.get('renderer')\n    if renderer is None:\n        # register a default renderer if you want super-dynamic\n        # rendering.  registering a default renderer will also allow\n        # override_renderer to work if a renderer is left unspecified for\n        # a view registration.\n        def viewresult_to_response(context, request):\n            result = view(context, request)\n            if result.__class__ is Response: # common case\n                response = result\n            else:\n                response = info.registry.queryAdapterOrSelf(result, IResponse)\n                if response is None:\n                    if result is None:\n                        append = (' You may have forgotten to return a value '\n                                  'from the view callable.')\n                    elif isinstance(result, dict):\n                        append = (' You may have forgotten to define a '\n                                  'renderer in the view configuration.')\n                    else:\n                        append = ''\n\n                    msg = ('Could not convert return value of the view '\n                           'callable %s into a response object. '\n                           'The value returned was %r.' + append)\n\n                    raise ValueError(msg % (view_description(view), result))\n\n            return response\n\n        return viewresult_to_response\n\n    if renderer is renderers.null_renderer:\n        return view\n\n    def rendered_view(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # potential common case\n            response = result\n        else:\n            # this must adapt, it can't do a simple interface check\n            # (avoid trying to render webob responses)\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                attrs = getattr(request, '__dict__', {})\n                if 'override_renderer' in attrs:\n                    # renderer overridden by newrequest event or other\n                    renderer_name = attrs.pop('override_renderer')\n                    view_renderer = renderers.RendererHelper(\n                        name=renderer_name,\n                        package=info.package,\n                        registry=info.registry)\n                else:\n                    view_renderer = renderer.clone()\n                if '__view__' in attrs:\n                    view_inst = attrs.pop('__view__')\n                else:\n                    view_inst = getattr(view, '__original_view__', view)\n                response = view_renderer.render_view(\n                    request, result, view_inst, context)\n        return response\n\n    return rendered_view\n\nrendered_view.options = ('renderer',)\n\ndef decorated_view(view, info):\n    decorator = info.options.get('decorator')\n    if decorator is None:\n        return view\n    return decorator(view)\n\ndecorated_view.options = ('decorator',)\n\nMAPPED_VIEW = 'mapped_view'\nINGRESS = 'INGRESS'\n",
            "new_file_content": "import inspect\n\nfrom zope.interface import (\n    implementer,\n    provider,\n    )\n\nfrom pyramid.security import NO_PERMISSION_REQUIRED\nfrom pyramid.response import Response\n\nfrom pyramid.interfaces import (\n    IAuthenticationPolicy,\n    IAuthorizationPolicy,\n    IDebugLogger,\n    IResponse,\n    IViewMapper,\n    IViewMapperFactory,\n    )\n\nfrom pyramid.compat import (\n    is_bound_method,\n    is_unbound_method,\n    )\n\nfrom pyramid.config.util import (\n    DEFAULT_PHASH,\n    MAX_ORDER,\n    takes_one_arg,\n    )\n\nfrom pyramid.exceptions import (\n    ConfigurationError,\n    PredicateMismatch,\n    )\nfrom pyramid.httpexceptions import HTTPForbidden\nfrom pyramid.util import object_description\nfrom pyramid.view import render_view_to_response\nfrom pyramid import renderers\n\n\ndef view_description(view):\n    try:\n        return view.__text__\n    except AttributeError:\n        # custom view mappers might not add __text__\n        return object_description(view)\n\ndef requestonly(view, attr=None):\n    return takes_one_arg(view, attr=attr, argname='request')\n\n@implementer(IViewMapper)\n@provider(IViewMapperFactory)\nclass DefaultViewMapper(object):\n    def __init__(self, **kw):\n        self.attr = kw.get('attr')\n\n    def __call__(self, view):\n        if is_unbound_method(view) and self.attr is None:\n            raise ConfigurationError((\n                'Unbound method calls are not supported, please set the class '\n                'as your `view` and the method as your `attr`'\n            ))\n\n        if inspect.isclass(view):\n            view = self.map_class(view)\n        else:\n            view = self.map_nonclass(view)\n        return view\n\n    def map_class(self, view):\n        ronly = requestonly(view, self.attr)\n        if ronly:\n            mapped_view = self.map_class_requestonly(view)\n        else:\n            mapped_view = self.map_class_native(view)\n        mapped_view.__text__ = 'method %s of %s' % (\n            self.attr or '__call__', object_description(view))\n        return mapped_view\n\n    def map_nonclass(self, view):\n        # We do more work here than appears necessary to avoid wrapping the\n        # view unless it actually requires wrapping (to avoid function call\n        # overhead).\n        mapped_view = view\n        ronly = requestonly(view, self.attr)\n        if ronly:\n            mapped_view = self.map_nonclass_requestonly(view)\n        elif self.attr:\n            mapped_view = self.map_nonclass_attr(view)\n        if inspect.isroutine(mapped_view):\n            # This branch will be true if the view is a function or a method.\n            # We potentially mutate an unwrapped object here if it's a\n            # function.  We do this to avoid function call overhead of\n            # injecting another wrapper.  However, we must wrap if the\n            # function is a bound method because we can't set attributes on a\n            # bound method.\n            if is_bound_method(view):\n                _mapped_view = mapped_view\n                def mapped_view(context, request):\n                    return _mapped_view(context, request)\n            if self.attr is not None:\n                mapped_view.__text__ = 'attr %s of %s' % (\n                    self.attr, object_description(view))\n            else:\n                mapped_view.__text__ = object_description(view)\n        return mapped_view\n\n    def map_class_requestonly(self, view):\n        # its a class that has an __init__ which only accepts request\n        attr = self.attr\n        def _class_requestonly_view(context, request):\n            inst = view(request)\n            request.__view__ = inst\n            if attr is None:\n                response = inst()\n            else:\n                response = getattr(inst, attr)()\n            return response\n        return _class_requestonly_view\n\n    def map_class_native(self, view):\n        # its a class that has an __init__ which accepts both context and\n        # request\n        attr = self.attr\n        def _class_view(context, request):\n            inst = view(context, request)\n            request.__view__ = inst\n            if attr is None:\n                response = inst()\n            else:\n                response = getattr(inst, attr)()\n            return response\n        return _class_view\n\n    def map_nonclass_requestonly(self, view):\n        # its a function that has a __call__ which accepts only a single\n        # request argument\n        attr = self.attr\n        def _requestonly_view(context, request):\n            if attr is None:\n                response = view(request)\n            else:\n                response = getattr(view, attr)(request)\n            return response\n        return _requestonly_view\n\n    def map_nonclass_attr(self, view):\n        # its a function that has a __call__ which accepts both context and\n        # request, but still has an attr\n        def _attr_view(context, request):\n            response = getattr(view, self.attr)(context, request)\n            return response\n        return _attr_view\n\n\ndef wraps_view(wrapper):\n    def inner(view, info):\n        wrapper_view = wrapper(view, info)\n        return preserve_view_attrs(view, wrapper_view)\n    return inner\n\ndef preserve_view_attrs(view, wrapper):\n    if view is None:\n        return wrapper\n\n    if wrapper is view:\n        return view\n\n    original_view = getattr(view, '__original_view__', None)\n\n    if original_view is None:\n        original_view = view\n\n    wrapper.__wraps__ = view\n    wrapper.__original_view__ = original_view\n    wrapper.__module__ = view.__module__\n    wrapper.__doc__ = view.__doc__\n\n    try:\n        wrapper.__name__ = view.__name__\n    except AttributeError:\n        wrapper.__name__ = repr(view)\n\n    # attrs that may not exist on \"view\", but, if so, must be attached to\n    # \"wrapped view\"\n    for attr in ('__permitted__', '__call_permissive__', '__permission__',\n                 '__predicated__', '__predicates__', '__accept__',\n                 '__order__', '__text__'):\n        try:\n            setattr(wrapper, attr, getattr(view, attr))\n        except AttributeError:\n            pass\n\n    return wrapper\n\ndef mapped_view(view, info):\n    mapper = info.options.get('mapper')\n    if mapper is None:\n        mapper = getattr(view, '__view_mapper__', None)\n        if mapper is None:\n            mapper = info.registry.queryUtility(IViewMapperFactory)\n            if mapper is None:\n                mapper = DefaultViewMapper\n\n    mapped_view = mapper(**info.options)(view)\n    return mapped_view\n\nmapped_view.options = ('mapper', 'attr')\n\ndef owrapped_view(view, info):\n    wrapper_viewname = info.options.get('wrapper')\n    viewname = info.options.get('name')\n    if not wrapper_viewname:\n        return view\n    def _owrapped_view(context, request):\n        response = view(context, request)\n        request.wrapped_response = response\n        request.wrapped_body = response.body\n        request.wrapped_view = view\n        wrapped_response = render_view_to_response(context, request,\n                                                   wrapper_viewname)\n        if wrapped_response is None:\n            raise ValueError(\n                'No wrapper view named %r found when executing view '\n                'named %r' % (wrapper_viewname, viewname))\n        return wrapped_response\n    return _owrapped_view\n\nowrapped_view.options = ('name', 'wrapper')\n\ndef http_cached_view(view, info):\n    if info.settings.get('prevent_http_cache', False):\n        return view\n\n    seconds = info.options.get('http_cache')\n\n    if seconds is None:\n        return view\n\n    options = {}\n\n    if isinstance(seconds, (tuple, list)):\n        try:\n            seconds, options = seconds\n        except ValueError:\n            raise ConfigurationError(\n                'If http_cache parameter is a tuple or list, it must be '\n                'in the form (seconds, options); not %s' % (seconds,))\n\n    def wrapper(context, request):\n        response = view(context, request)\n        prevent_caching = getattr(response.cache_control, 'prevent_auto',\n                                  False)\n        if not prevent_caching:\n            response.cache_expires(seconds, **options)\n        return response\n\n    return wrapper\n\nhttp_cached_view.options = ('http_cache',)\n\ndef secured_view(view, info):\n    for wrapper in (_secured_view, _authdebug_view):\n        view = wraps_view(wrapper)(view, info)\n    return view\n\nsecured_view.options = ('permission',)\n\ndef _secured_view(view, info):\n    permission = info.options.get('permission')\n    if permission == NO_PERMISSION_REQUIRED:\n        # allow views registered within configurations that have a\n        # default permission to explicitly override the default\n        # permission, replacing it with no permission at all\n        permission = None\n\n    wrapped_view = view\n    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)\n    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)\n\n    if authn_policy and authz_policy and (permission is not None):\n        def _permitted(context, request):\n            principals = authn_policy.effective_principals(request)\n            return authz_policy.permits(context, principals, permission)\n        def _secured_view(context, request):\n            result = _permitted(context, request)\n            if result:\n                return view(context, request)\n            view_name = getattr(view, '__name__', view)\n            msg = getattr(\n                request, 'authdebug_message',\n                'Unauthorized: %s failed permission check' % view_name)\n            raise HTTPForbidden(msg, result=result)\n        _secured_view.__call_permissive__ = view\n        _secured_view.__permitted__ = _permitted\n        _secured_view.__permission__ = permission\n        wrapped_view = _secured_view\n\n    return wrapped_view\n\ndef _authdebug_view(view, info):\n    wrapped_view = view\n    settings = info.settings\n    permission = info.options.get('permission')\n    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)\n    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)\n    logger = info.registry.queryUtility(IDebugLogger)\n    if settings and settings.get('debug_authorization', False):\n        def _authdebug_view(context, request):\n            view_name = getattr(request, 'view_name', None)\n\n            if authn_policy and authz_policy:\n                if permission is NO_PERMISSION_REQUIRED:\n                    msg = 'Allowed (NO_PERMISSION_REQUIRED)'\n                elif permission is None:\n                    msg = 'Allowed (no permission registered)'\n                else:\n                    principals = authn_policy.effective_principals(request)\n                    msg = str(authz_policy.permits(\n                        context, principals, permission))\n            else:\n                msg = 'Allowed (no authorization policy in use)'\n\n            view_name = getattr(request, 'view_name', None)\n            url = getattr(request, 'url', None)\n            msg = ('debug_authorization of url %s (view name %r against '\n                   'context %r): %s' % (url, view_name, context, msg))\n            if logger:\n                logger.debug(msg)\n            if request is not None:\n                request.authdebug_message = msg\n            return view(context, request)\n\n        wrapped_view = _authdebug_view\n\n    return wrapped_view\n\ndef predicated_view(view, info):\n    preds = info.predicates\n    if not preds:\n        return view\n    def predicate_wrapper(context, request):\n        for predicate in preds:\n            if not predicate(context, request):\n                view_name = getattr(view, '__name__', view)\n                raise PredicateMismatch(\n                    'predicate mismatch for view %s (%s)' % (\n                        view_name, predicate.text()))\n        return view(context, request)\n    def checker(context, request):\n        return all((predicate(context, request) for predicate in\n                    preds))\n    predicate_wrapper.__predicated__ = checker\n    predicate_wrapper.__predicates__ = preds\n    return predicate_wrapper\n\ndef attr_wrapped_view(view, info):\n    accept, order, phash = (info.options.get('accept', None),\n                            getattr(info, 'order', MAX_ORDER),\n                            getattr(info, 'phash', DEFAULT_PHASH))\n    # this is a little silly but we don't want to decorate the original\n    # function with attributes that indicate accept, order, and phash,\n    # so we use a wrapper\n    if (\n        (accept is None) and\n        (order == MAX_ORDER) and\n        (phash == DEFAULT_PHASH)\n    ):\n        return view # defaults\n    def attr_view(context, request):\n        return view(context, request)\n    attr_view.__accept__ = accept\n    attr_view.__order__ = order\n    attr_view.__phash__ = phash\n    attr_view.__view_attr__ = info.options.get('attr')\n    attr_view.__permission__ = info.options.get('permission')\n    return attr_view\n\nattr_wrapped_view.options = ('accept', 'attr', 'permission')\n\ndef rendered_view(view, info):\n    # one way or another this wrapper must produce a Response (unless\n    # the renderer is a NullRendererHelper)\n    renderer = info.options.get('renderer')\n    if renderer is None:\n        # register a default renderer if you want super-dynamic\n        # rendering.  registering a default renderer will also allow\n        # override_renderer to work if a renderer is left unspecified for\n        # a view registration.\n        def viewresult_to_response(context, request):\n            result = view(context, request)\n            if result.__class__ is Response: # common case\n                response = result\n            else:\n                response = info.registry.queryAdapterOrSelf(result, IResponse)\n                if response is None:\n                    if result is None:\n                        append = (' You may have forgotten to return a value '\n                                  'from the view callable.')\n                    elif isinstance(result, dict):\n                        append = (' You may have forgotten to define a '\n                                  'renderer in the view configuration.')\n                    else:\n                        append = ''\n\n                    msg = ('Could not convert return value of the view '\n                           'callable %s into a response object. '\n                           'The value returned was %r.' + append)\n\n                    raise ValueError(msg % (view_description(view), result))\n\n            return response\n\n        return viewresult_to_response\n\n    if renderer is renderers.null_renderer:\n        return view\n\n    def rendered_view(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # potential common case\n            response = result\n        else:\n            # this must adapt, it can't do a simple interface check\n            # (avoid trying to render webob responses)\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                attrs = getattr(request, '__dict__', {})\n                if 'override_renderer' in attrs:\n                    # renderer overridden by newrequest event or other\n                    renderer_name = attrs.pop('override_renderer')\n                    view_renderer = renderers.RendererHelper(\n                        name=renderer_name,\n                        package=info.package,\n                        registry=info.registry)\n                else:\n                    view_renderer = renderer.clone()\n                if '__view__' in attrs:\n                    view_inst = attrs.pop('__view__')\n                else:\n                    view_inst = getattr(view, '__original_view__', view)\n                response = view_renderer.render_view(\n                    request, result, view_inst, context)\n        return response\n\n    return rendered_view\n\nrendered_view.options = ('renderer',)\n\ndef decorated_view(view, info):\n    decorator = info.options.get('decorator')\n    if decorator is None:\n        return view\n    return decorator(view)\n\ndecorated_view.options = ('decorator',)\n\nVIEW = 'VIEW'\nINGRESS = 'INGRESS'\n",
            "header": {
                "file": {
                    "path": "pyramid/viewderivers.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "f97099cc8",
                "new_commit_hash": "8061e5d4a",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/pyramid/viewderivers.py"
            },
            "plus_file": {
                "path": "b/pyramid/viewderivers.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 455,
                            "length": 5
                        },
                        "new_range": {
                            "start": 455,
                            "length": 5
                        },
                        "section": "def decorated_view(view, info):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "decorated_view.options = ('decorator',)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "MAPPED_VIEW = 'mapped_view'",
                                "type": "deleted"
                            },
                            {
                                "content": "VIEW = 'VIEW'",
                                "type": "added"
                            },
                            {
                                "content": "INGRESS = 'INGRESS'",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "pyramid/viewderivers.py",
                            "type": "statement",
                            "name": "",
                            "content": "VIEW = 'VIEW'",
                            "ast_type_str": "Assign",
                            "start_lineno": 458,
                            "end_lineno": 458,
                            "parent": null
                        }
                    ],
                    "deleted_entities": [
                        {
                            "file_name": "pyramid/viewderivers.py",
                            "type": "statement",
                            "name": "",
                            "content": "MAPPED_VIEW = 'mapped_view'",
                            "ast_type_str": "Assign",
                            "start_lineno": 458,
                            "end_lineno": 458,
                            "parent": null
                        }
                    ]
                }
            ]
        }
    ],
    "old_commit_hash": "c231d8174e811eec5a3faeafa5aee60757c6d31f^",
    "new_commit_hash": "c231d8174e811eec5a3faeafa5aee60757c6d31f",
    "commit_message": "update constraints for derivers as well as docs",
    "commit_date": "2016-04-08T00:47:01-05:00",
    "metadata": {}
}
{
    "repo_name": "pyramid",
    "new_commit_hash": "c231d8174e811eec5a3faeafa5aee60757c6d31f",
    "test_file_codes": [
        "import unittest\nfrom zope.interface import implementer\n\nfrom pyramid import testing\nfrom pyramid.exceptions import ConfigurationError\nfrom pyramid.interfaces import (\n    IResponse,\n    IRequest,\n    )\n\nclass TestDeriveView(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def _makeRequest(self):\n        request = DummyRequest()\n        request.registry = self.config.registry\n        return request\n\n    def _registerLogger(self):\n        from pyramid.interfaces import IDebugLogger\n        logger = DummyLogger()\n        self.config.registry.registerUtility(logger, IDebugLogger)\n        return logger\n\n    def _registerSecurityPolicy(self, permissive):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(permissive)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n\n    def test_function_returns_non_adaptable(self):\n        def view(request):\n            return None\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable function '\n                'pyramid.tests.test_viewderivers.view into a response '\n                'object. The value returned was None. You may have forgotten '\n                'to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_function_returns_non_adaptable_dict(self):\n        def view(request):\n            return {'a':1}\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                \"Could not convert return value of the view callable function \"\n                \"pyramid.tests.test_viewderivers.view into a response \"\n                \"object. The value returned was {'a': 1}. You may have \"\n                \"forgotten to define a renderer in the view configuration.\"\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_instance_returns_non_adaptable(self):\n        class AView(object):\n            def __call__(self, request):\n                return None\n        view = AView()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            msg = e.args[0]\n            self.assertTrue(msg.startswith(\n                'Could not convert return value of the view callable object '\n                '<pyramid.tests.test_viewderivers.'))\n            self.assertTrue(msg.endswith(\n                '> into a response object. The value returned was None. You '\n                'may have forgotten to return a value from the view callable.'))\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_function_returns_true_Response_no_renderer(self):\n        from pyramid.response import Response\n        r = Response('Hello')\n        def view(request):\n            return r\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        response = result(None, None)\n        self.assertEqual(response, r)\n\n    def test_function_returns_true_Response_with_renderer(self):\n        from pyramid.response import Response\n        r = Response('Hello')\n        def view(request):\n            return r\n        renderer = object()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        response = result(None, None)\n        self.assertEqual(response, r)\n\n    def test_requestonly_default_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return None\n        result = self.config.derive_view(AView)\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method __call__ of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_requestonly_nondefault_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def theviewmethod(self):\n                return None\n        result = self.config.derive_view(AView, attr='theviewmethod')\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n            self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method theviewmethod of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_requestonly_function(self):\n        response = DummyResponse()\n        def view(request):\n            return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_requestonly_function_with_renderer(self):\n        response = DummyResponse()\n        class moo(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, 'OK')\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        def view(request):\n            return 'OK'\n        result = self.config.derive_view(view, renderer=moo())\n        self.assertFalse(result.__wraps__ is view)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_requestonly_function_with_renderer_request_override(self):\n        def moo(info):\n            def inner(value, system):\n                self.assertEqual(value, 'OK')\n                self.assertEqual(system['request'], request)\n                self.assertEqual(system['context'], context)\n                return b'moo'\n            return inner\n        def view(request):\n            return 'OK'\n        self.config.add_renderer('moo', moo)\n        result = self.config.derive_view(view, renderer='string')\n        self.assertFalse(result is view)\n        request = self._makeRequest()\n        request.override_renderer = 'moo'\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request).body, b'moo')\n\n    def test_requestonly_function_with_renderer_request_has_view(self):\n        response = DummyResponse()\n        class moo(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, 'OK')\n                self.assertEqual(view_inst, 'view')\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        def view(request):\n            return 'OK'\n        result = self.config.derive_view(view, renderer=moo())\n        self.assertFalse(result.__wraps__ is view)\n        request = self._makeRequest()\n        request.__view__ = 'view'\n        context = testing.DummyResource()\n        r = result(context, request)\n        self.assertEqual(r, response)\n        self.assertFalse(hasattr(request, '__view__'))\n\n    def test_class_without_attr(self):\n        response = DummyResponse()\n        class View(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(View)\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, View)\n\n    def test_class_with_attr(self):\n        response = DummyResponse()\n        class View(object):\n            def __init__(self, request):\n                pass\n            def another(self):\n                return response\n        result = self.config.derive_view(View, attr='another')\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, View)\n\n    def test_as_function_context_and_request(self):\n        def view(context, request):\n            return 'OK'\n        result = self.config.derive_view(view)\n        self.assertTrue(result.__wraps__ is view)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(view(None, None), 'OK')\n\n    def test_as_function_requestonly(self):\n        response = DummyResponse()\n        def view(request):\n            return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_as_newstyle_class_context_and_request(self):\n        response = DummyResponse()\n        class view(object):\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_newstyle_class_requestonly(self):\n        response = DummyResponse()\n        class view(object):\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_oldstyle_class_context_and_request(self):\n        response = DummyResponse()\n        class view:\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_oldstyle_class_requestonly(self):\n        response = DummyResponse()\n        class view:\n            def __init__(self, context, request):\n                pass\n            def __call__(self):\n                return response\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(request.__view__.__class__, view)\n\n    def test_as_instance_context_and_request(self):\n        response = DummyResponse()\n        class View:\n            def __call__(self, context, request):\n                return response\n        view = View()\n        result = self.config.derive_view(view)\n        self.assertTrue(result.__wraps__ is view)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_as_instance_requestonly(self):\n        response = DummyResponse()\n        class View:\n            def __call__(self, request):\n                return response\n        view = View()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertTrue('test_viewderivers' in result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        self.assertEqual(result(None, None), response)\n\n    def test_with_debug_authorization_no_authpol(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_authn_policy_no_authz_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(debug_authorization=True)\n        from pyramid.interfaces import IAuthenticationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_authz_policy_no_authn_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(debug_authorization=True)\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed \"\n                         \"(no authorization policy in use)\")\n\n    def test_with_debug_authorization_no_permission(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        self._registerSecurityPolicy(True)\n        logger = self._registerLogger()\n        result = self.config._derive_view(view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): Allowed (\"\n                         \"no permission registered)\")\n\n    def test_debug_auth_permission_authpol_permitted(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(True)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): True\")\n\n    def test_debug_auth_permission_authpol_permitted_no_request(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(True)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        self.assertEqual(result(None, None), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url None (view name \"\n                         \"None against context None): True\")\n\n    def test_debug_auth_permission_authpol_denied(self):\n        from pyramid.httpexceptions import HTTPForbidden\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertEqual(result.__call_permissive__.__wraps__, view)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertRaises(HTTPForbidden, result, None, request)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): False\")\n\n    def test_debug_auth_permission_authpol_denied2(self):\n        view = lambda *arg: 'OK'\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        permitted = result.__permitted__(None, None)\n        self.assertEqual(permitted, False)\n\n    def test_debug_auth_permission_authpol_overridden(self):\n        from pyramid.security import NO_PERMISSION_REQUIRED\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = dict(\n            debug_authorization=True, reload_templates=True)\n        logger = self._registerLogger()\n        self._registerSecurityPolicy(False)\n        result = self.config._derive_view(view, permission=NO_PERMISSION_REQUIRED)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n        self.assertEqual(len(logger.messages), 1)\n        self.assertEqual(logger.messages[0],\n                         \"debug_authorization of url url (view name \"\n                         \"'view_name' against context None): \"\n                         \"Allowed (NO_PERMISSION_REQUIRED)\")\n\n    def test_secured_view_authn_policy_no_authz_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        from pyramid.interfaces import IAuthenticationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n\n    def test_secured_view_authz_policy_no_authn_policy(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        from pyramid.interfaces import IAuthorizationPolicy\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n        self.assertEqual(view.__name__, result.__name__)\n        self.assertFalse(hasattr(result, '__call_permissive__'))\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        self.assertEqual(result(None, request), response)\n\n    def test_secured_view_raises_forbidden_no_name(self):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        from pyramid.httpexceptions import HTTPForbidden\n        response = DummyResponse()\n        view = lambda *arg: response\n        self.config.registry.settings = {}\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(view, permission='view')\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        try:\n            result(None, request)\n        except HTTPForbidden as e:\n            self.assertEqual(e.message,\n                             'Unauthorized: <lambda> failed permission check')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_secured_view_raises_forbidden_with_name(self):\n        from pyramid.interfaces import IAuthenticationPolicy\n        from pyramid.interfaces import IAuthorizationPolicy\n        from pyramid.httpexceptions import HTTPForbidden\n        def myview(request): pass\n        self.config.registry.settings = {}\n        policy = DummySecurityPolicy(False)\n        self.config.registry.registerUtility(policy, IAuthenticationPolicy)\n        self.config.registry.registerUtility(policy, IAuthorizationPolicy)\n        result = self.config._derive_view(myview, permission='view')\n        request = self._makeRequest()\n        request.view_name = 'view_name'\n        request.url = 'url'\n        try:\n            result(None, request)\n        except HTTPForbidden as e:\n            self.assertEqual(e.message,\n                             'Unauthorized: myview failed permission check')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_view_has_no_name(self):\n        from pyramid.exceptions import PredicateMismatch\n        response = DummyResponse()\n        view = lambda *arg: response\n        def predicate1(context, request):\n            return False\n        predicate1.text = lambda *arg: 'text'\n        result = self.config._derive_view(view, predicates=[predicate1])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view <lambda> (text)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_view_has_name(self):\n        from pyramid.exceptions import PredicateMismatch\n        def myview(request): pass\n        def predicate1(context, request):\n            return False\n        predicate1.text = lambda *arg: 'text'\n        result = self.config._derive_view(myview, predicates=[predicate1])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view myview (text)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_predicate_mismatch_exception_has_text_in_detail(self):\n        from pyramid.exceptions import PredicateMismatch\n        def myview(request): pass\n        def predicate1(context, request):\n            return True\n        predicate1.text = lambda *arg: 'pred1'\n        def predicate2(context, request):\n            return False\n        predicate2.text = lambda *arg: 'pred2'\n        result = self.config._derive_view(myview, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        try:\n            result(None, None)\n        except PredicateMismatch as e:\n            self.assertEqual(e.detail,\n                             'predicate mismatch for view myview (pred2)')\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_with_predicates_all(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        def predicate2(context, request):\n            predicates.append(True)\n            return True\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        next = result(None, None)\n        self.assertEqual(next, response)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_predicates_checker(self):\n        view = lambda *arg: 'OK'\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        def predicate2(context, request):\n            predicates.append(True)\n            return True\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        next = result.__predicated__(None, None)\n        self.assertEqual(next, True)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_predicates_notall(self):\n        from pyramid.httpexceptions import HTTPNotFound\n        view = lambda *arg: 'OK'\n        predicates = []\n        def predicate1(context, request):\n            predicates.append(True)\n            return True\n        predicate1.text = lambda *arg: 'text'\n        def predicate2(context, request):\n            predicates.append(True)\n            return False\n        predicate2.text = lambda *arg: 'text'\n        result = self.config._derive_view(view, \n            predicates=[predicate1, predicate2])\n        request = self._makeRequest()\n        request.method = 'POST'\n        self.assertRaises(HTTPNotFound, result, None, None)\n        self.assertEqual(predicates, [True, True])\n\n    def test_with_wrapper_viewname(self):\n        from pyramid.response import Response\n        from pyramid.interfaces import IView\n        from pyramid.interfaces import IViewClassifier\n        inner_response = Response('OK')\n        def inner_view(context, request):\n            return inner_response\n        def outer_view(context, request):\n            self.assertEqual(request.wrapped_response, inner_response)\n            self.assertEqual(request.wrapped_body, inner_response.body)\n            self.assertEqual(request.wrapped_view.__original_view__,\n                             inner_view)\n            return Response(b'outer ' + request.wrapped_body)\n        self.config.registry.registerAdapter(\n            outer_view, (IViewClassifier, None, None), IView, 'owrap')\n        result = self.config._derive_view(inner_view, viewname='inner',\n                                wrapper_viewname='owrap')\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        response = result(None, request)\n        self.assertEqual(response.body, b'outer OK')\n\n    def test_with_wrapper_viewname_notfound(self):\n        from pyramid.response import Response\n        inner_response = Response('OK')\n        def inner_view(context, request):\n            return inner_response\n        wrapped = self.config._derive_view(inner_view, viewname='inner',\n                                wrapper_viewname='owrap')\n        request = self._makeRequest()\n        self.assertRaises(ValueError, wrapped, None, request)\n\n    def test_as_newstyle_class_context_and_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View(object):\n            def __init__(self, context, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config._derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_newstyle_class_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View(object):\n            def __init__(self, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_oldstyle_cls_context_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def __init__(self, context, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_oldstyle_cls_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst.__class__, View)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def __init__(self, request):\n                pass\n            def index(self):\n                return {'a':'1'}\n        result = self.config.derive_view(View, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is View)\n        self.assertEqual(result.__module__, View.__module__)\n        self.assertEqual(result.__doc__, View.__doc__)\n        self.assertEqual(result.__name__, View.__name__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_instance_context_and_request_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def index(self, context, request):\n                return {'a':'1'}\n        view = View()\n        result = self.config.derive_view(view, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is view)\n        self.assertEqual(result.__module__, view.__module__)\n        self.assertEqual(result.__doc__, view.__doc__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_as_instance_requestonly_attr_and_renderer(self):\n        response = DummyResponse()\n        class renderer(object):\n            def render_view(inself, req, resp, view_inst, ctx):\n                self.assertEqual(req, request)\n                self.assertEqual(resp, {'a':'1'})\n                self.assertEqual(view_inst, view)\n                self.assertEqual(ctx, context)\n                return response\n            def clone(self):\n                return self\n        class View:\n            def index(self, request):\n                return {'a':'1'}\n        view = View()\n        result = self.config.derive_view(view, \n            renderer=renderer(), attr='index')\n        self.assertFalse(result is view)\n        self.assertEqual(result.__module__, view.__module__)\n        self.assertEqual(result.__doc__, view.__doc__)\n        request = self._makeRequest()\n        context = testing.DummyResource()\n        self.assertEqual(result(context, request), response)\n\n    def test_with_view_mapper_config_specified(self):\n        response = DummyResponse()\n        class mapper(object):\n            def __init__(self, **kw):\n                self.kw = kw\n            def __call__(self, view):\n                def wrapped(context, request):\n                    return response\n                return wrapped\n        def view(context, request): return 'NOTOK'\n        result = self.config._derive_view(view, mapper=mapper)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_with_view_mapper_view_specified(self):\n        from pyramid.response import Response\n        response = Response()\n        def mapper(**kw):\n            def inner(view):\n                def superinner(context, request):\n                    self.assertEqual(request, None)\n                    return response\n                return superinner\n            return inner\n        def view(context, request): return 'NOTOK'\n        view.__view_mapper__ = mapper\n        result = self.config.derive_view(view)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_with_view_mapper_default_mapper_specified(self):\n        from pyramid.response import Response\n        response = Response()\n        def mapper(**kw):\n            def inner(view):\n                def superinner(context, request):\n                    self.assertEqual(request, None)\n                    return  response\n                return superinner\n            return inner\n        self.config.set_view_mapper(mapper)\n        def view(context, request): return 'NOTOK'\n        result = self.config.derive_view(view)\n        self.assertFalse(result.__wraps__ is view)\n        self.assertEqual(result(None, None), response)\n\n    def test_attr_wrapped_view_branching_default_phash(self):\n        from pyramid.config.util import DEFAULT_PHASH\n        def view(context, request): pass\n        result = self.config._derive_view(view, phash=DEFAULT_PHASH)\n        self.assertEqual(result.__wraps__, view)\n\n    def test_attr_wrapped_view_branching_nondefault_phash(self):\n        def view(context, request): pass\n        result = self.config._derive_view(view, phash='nondefault')\n        self.assertNotEqual(result, view)\n\n    def test_http_cached_view_integer(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600')\n\n    def test_http_cached_view_timedelta(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, \n            http_cache=datetime.timedelta(hours=1))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600')\n\n    def test_http_cached_view_tuple(self):\n        import datetime\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view,\n            http_cache=(3600, {'public':True}))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        when = datetime.datetime.utcnow() + datetime.timedelta(hours=1)\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        expires = parse_httpdate(headers['Expires'])\n        assert_similar_datetime(expires, when)\n        self.assertEqual(headers['Cache-Control'], 'max-age=3600, public')\n\n    def test_http_cached_view_tuple_seconds_None(self):\n        from pyramid.response import Response\n        response = Response('OK')\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view,\n            http_cache=(None, {'public':True}))\n        self.assertFalse(result is inner_view)\n        self.assertEqual(inner_view.__module__, result.__module__)\n        self.assertEqual(inner_view.__doc__, result.__doc__)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertEqual(headers['Cache-Control'], 'public')\n\n    def test_http_cached_view_prevent_auto_set(self):\n        from pyramid.response import Response\n        response = Response()\n        response.cache_control.prevent_auto = True\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response) # doesn't blow up\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertFalse('Cache-Control' in headers)\n\n    def test_http_cached_prevent_http_cache_in_settings(self):\n        self.config.registry.settings['prevent_http_cache'] = True\n        from pyramid.response import Response\n        response = Response()\n        def inner_view(context, request):\n            return response\n        result = self.config._derive_view(inner_view, http_cache=3600)\n        request = self._makeRequest()\n        result = result(None, request)\n        self.assertEqual(result, response)\n        headers = dict(result.headerlist)\n        self.assertFalse('Expires' in headers)\n        self.assertFalse('Cache-Control' in headers)\n\n    def test_http_cached_view_bad_tuple(self):\n        def view(request): pass\n        self.assertRaises(ConfigurationError, self.config._derive_view, \n            view, http_cache=(None,))\n\n\nclass TestDerivationOrder(unittest.TestCase):\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_right_order_user_sorted(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1')\n        self.config.add_view_deriver(None, 'deriv2', 'decorated_view', 'deriv1')\n        self.config.add_view_deriver(None, 'deriv3', 'deriv2', 'deriv1')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv2',\n            'deriv3',\n            'deriv1',\n            'rendered_view',\n            'mapped_view',\n            ], dlist)\n\n    def test_right_order_implicit(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1')\n        self.config.add_view_deriver(None, 'deriv2')\n        self.config.add_view_deriver(None, 'deriv3')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv3',\n            'deriv2',\n            'deriv1',\n            'rendered_view',\n            'mapped_view',\n            ], dlist)\n\n    def test_right_order_under_rendered_view(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1', 'rendered_view', 'mapped_view')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'rendered_view',\n            'deriv1',\n            'mapped_view',\n            ], dlist)\n\n\n    def test_right_order_under_rendered_view_others(self):\n        from pyramid.interfaces import IViewDerivers\n\n        self.config.add_view_deriver(None, 'deriv1', 'rendered_view', 'mapped_view')\n        self.config.add_view_deriver(None, 'deriv2')\n        self.config.add_view_deriver(None, 'deriv3')\n\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        derivers_sorted = derivers.sorted()\n        dlist = [d for (d, _) in derivers_sorted]\n        self.assertEqual([\n            'secured_view',\n            'owrapped_view',\n            'http_cached_view',\n            'decorated_view',\n            'deriv3',\n            'deriv2',\n            'rendered_view',\n            'deriv1',\n            'mapped_view',\n            ], dlist)\n\n\nclass TestAddDeriver(unittest.TestCase):\n\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def test_add_single_deriver(self):\n        response = DummyResponse()\n        response.deriv = False\n        view = lambda *arg: response\n\n        def deriv(view, info):\n            self.assertFalse(response.deriv)\n            response.deriv = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(response.deriv)\n        self.config.add_view_deriver(deriv, 'test_deriv')\n\n        result = self.config._derive_view(view)\n        self.assertTrue(response.deriv)\n\n    def test_override_deriver(self):\n        flags = {}\n\n        class AView:\n            def __init__(self):\n                self.response = DummyResponse()\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        def deriv2(view, info):\n            flags['deriv2'] = True\n            return view\n\n        view1 = AView()\n        self.config.add_view_deriver(deriv1, 'test_deriv')\n        result = self.config._derive_view(view1)\n        self.assertTrue(flags.get('deriv1'))\n        self.assertFalse(flags.get('deriv2'))\n\n        flags.clear()\n        view2 = AView()\n        self.config.add_view_deriver(deriv2, 'test_deriv')\n        result = self.config._derive_view(view2)\n        self.assertFalse(flags.get('deriv1'))\n        self.assertTrue(flags.get('deriv2'))\n\n    def test_override_mapped_view(self):\n        from pyramid.viewderivers import VIEW\n        response = DummyResponse()\n        view = lambda *arg: response\n        flags = {}\n\n        def deriv1(view, info):\n            flags['deriv1'] = True\n            return view\n\n        result = self.config._derive_view(view)\n        self.assertFalse(flags.get('deriv1'))\n\n        flags.clear()\n        self.config.add_view_deriver(\n            deriv1, name='mapped_view', under='rendered_view', over=VIEW)\n        result = self.config._derive_view(view)\n        self.assertTrue(flags.get('deriv1'))\n\n    def test_add_multi_derivers_ordered(self):\n        from pyramid.viewderivers import INGRESS\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append('deriv1')\n            return view\n\n        def deriv2(view, info):\n            response.deriv.append('deriv2')\n            return view\n\n        def deriv3(view, info):\n            response.deriv.append('deriv3')\n            return view\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2', INGRESS, 'deriv1')\n        self.config.add_view_deriver(deriv3, 'deriv3', 'deriv2', 'deriv1')\n        result = self.config._derive_view(view)\n        self.assertEqual(response.deriv, ['deriv1', 'deriv3', 'deriv2'])\n\n    def test_add_deriver_without_name(self):\n        from pyramid.interfaces import IViewDerivers\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1)\n        derivers = self.config.registry.getUtility(IViewDerivers)\n        self.assertTrue('deriv1' in derivers.names)\n\n    def test_add_deriver_reserves_ingress(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        self.assertRaises(\n            ConfigurationError, self.config.add_view_deriver, deriv1, INGRESS)\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over=INGRESS)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be over INGRESS' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import VIEW\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, under=VIEW)\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under VIEW' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n        except ConfigurationError as ex:\n            self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])\n        else: # pragma: no cover\n            raise AssertionError\n\n\nclass TestDeriverIntegration(unittest.TestCase):\n    def setUp(self):\n        self.config = testing.setUp()\n\n    def tearDown(self):\n        self.config = None\n        testing.tearDown()\n\n    def _getViewCallable(self, config, ctx_iface=None, request_iface=None,\n                         name=''):\n        from zope.interface import Interface\n        from pyramid.interfaces import IRequest\n        from pyramid.interfaces import IView\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import IExceptionViewClassifier\n        classifier = IViewClassifier\n        if ctx_iface is None:\n            ctx_iface = Interface\n        if request_iface is None:\n            request_iface = IRequest\n        return config.registry.adapters.lookup(\n            (classifier, request_iface, ctx_iface), IView, name=name,\n            default=None)\n\n    def _makeRequest(self, config):\n        request = DummyRequest()\n        request.registry = config.registry\n        return request\n\n    def test_view_options(self):\n        response = DummyResponse()\n        view = lambda *arg: response\n        response.deriv = []\n\n        def deriv1(view, info):\n            response.deriv.append(info.options['deriv1'])\n            return view\n        deriv1.options = ('deriv1',)\n\n        def deriv2(view, info):\n            response.deriv.append(info.options['deriv2'])\n            return view\n        deriv2.options = ('deriv2',)\n\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.config.add_view_deriver(deriv2, 'deriv2')\n        self.config.add_view(view, deriv1='test1', deriv2='test2')\n\n        wrapper = self._getViewCallable(self.config)\n        request = self._makeRequest(self.config)\n        request.method = 'GET'\n        self.assertEqual(wrapper(None, request), response)\n        self.assertEqual(['test1', 'test2'], response.deriv)\n\n    def test_unexpected_view_options(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        self.config.add_view_deriver(deriv1, 'deriv1')\n        self.assertRaises(\n            ConfigurationError,\n            lambda: self.config.add_view(lambda r: {}, deriv1='test1'))\n\n@implementer(IResponse)\nclass DummyResponse(object):\n    content_type = None\n    default_content_type = None\n    body = None\n\nclass DummyRequest:\n    subpath = ()\n    matchdict = None\n    request_iface  = IRequest\n\n    def __init__(self, environ=None):\n        if environ is None:\n            environ = {}\n        self.environ = environ\n        self.params = {}\n        self.cookies = {}\n        self.response = DummyResponse()\n\nclass DummyLogger:\n    def __init__(self):\n        self.messages = []\n    def info(self, msg):\n        self.messages.append(msg)\n    warn = info\n    debug = info\n\nclass DummySecurityPolicy:\n    def __init__(self, permitted=True):\n        self.permitted = permitted\n\n    def effective_principals(self, request):\n        return []\n\n    def permits(self, context, principals, permission):\n        return self.permitted\n\ndef parse_httpdate(s):\n    import datetime\n    # cannot use %Z, must use literal GMT; Jython honors timezone\n    # but CPython does not\n    return datetime.datetime.strptime(s, \"%a, %d %b %Y %H:%M:%S GMT\")\n\ndef assert_similar_datetime(one, two):\n    for attr in ('year', 'month', 'day', 'hour', 'minute'):\n        one_attr = getattr(one, attr)\n        two_attr = getattr(two, attr)\n        if not one_attr == two_attr: # pragma: no cover\n            raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr))\n"
    ],
    "test_file_names": [
        "test_1.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "",
    "setup_res_stderr": "Using CPython 3.8.20\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 9 packages in 675ms\nPrepared 1 package in 913ms\nInstalled 9 packages in 20ms\n + pastedeploy==3.1.0\n + pyramid==1.7.dev0 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f)\n + repoze-lru==0.7\n + setuptools==75.3.0\n + translationstring==1.4\n + venusian==3.1.1\n + webob==1.8.9\n + zope-deprecation==5.0\n + zope-interface==7.2\nResolved 19 packages in 18ms\nInstalled 10 packages in 28ms\n + beautifulsoup4==4.12.3\n + coverage==7.6.1\n + distlib==0.3.9\n + filelock==3.16.1\n + nose==1.3.7\n + platformdirs==4.3.6\n + soupsieve==2.6\n + virtualenv==20.29.0\n + waitress==3.0.0\n + webtest==3.0.1\nResolved 16 packages in 8ms\nInstalled 12 packages in 11ms\n + cachetools==5.5.0\n + chardet==5.2.0\n + colorama==0.4.6\n + exceptiongroup==1.2.2\n + iniconfig==2.0.0\n + packaging==24.2\n + pluggy==1.5.0\n + pyproject-api==1.8.0\n + pytest==8.3.4\n + tomli==2.2.1\n + tox==4.23.2\n + typing-extensions==4.12.2\n",
    "new_commit_res_code": 1,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.8.20, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f\ncollected 963 items\n\nr2e_tests/test_1.py ....F..................FF.........F...F....F........ [  5%]\n.......................                                                  [  7%]\nr2e_tests/test_config/test_adapters.py .FF..............F...             [  9%]\nr2e_tests/test_config/test_assets.py ....F.F...F...FF.FF................ [ 13%]\n.....................................F.F................................ [ 21%]\n                                                                         [ 21%]\nr2e_tests/test_config/test_factories.py .....................            [ 23%]\nr2e_tests/test_config/test_i18n.py FFF.FF...                             [ 24%]\nr2e_tests/test_config/test_init.py ..................................... [ 28%]\n...F..F.......F.............F...........F.....................FF...FFF.. [ 35%]\n......................                                                   [ 37%]\nr2e_tests/test_config/test_predicates.py ............................... [ 41%]\n...........................................                              [ 45%]\nr2e_tests/test_config/test_rendering.py ...                              [ 45%]\nr2e_tests/test_config/test_routes.py ........................            [ 48%]\nr2e_tests/test_config/test_security.py ..........                        [ 49%]\nr2e_tests/test_config/test_settings.py ........................          [ 51%]\nr2e_tests/test_config/test_testing.py ............                       [ 53%]\nr2e_tests/test_config/test_tweens.py .................................   [ 56%]\nr2e_tests/test_config/test_util.py ..................................... [ 60%]\n..............                                                           [ 61%]\nr2e_tests/test_config/test_views.py ........................F........... [ 65%]\n........................................................................ [ 73%]\n......FF................................................................ [ 80%]\n..................................F.......F                              [ 84%]\nr2e_tests/test_scripts/test_common.py ...                                [ 85%]\nr2e_tests/test_scripts/test_pcreate.py ....................              [ 87%]\nr2e_tests/test_scripts/test_pdistreport.py ..                            [ 87%]\nr2e_tests/test_scripts/test_prequest.py F.FFF.FFFFFF.F.FFF.              [ 89%]\nr2e_tests/test_scripts/test_proutes.py ...FFF....FFFF.F.FF....F..FF.     [ 92%]\nr2e_tests/test_scripts/test_pserve.py ............................       [ 95%]\nr2e_tests/test_scripts/test_pshell.py ................                   [ 97%]\nr2e_tests/test_scripts/test_ptweens.py .....                             [ 97%]\nr2e_tests/test_scripts/test_pviews.py ................F......            [100%]\n\n=================================== FAILURES ===================================\n_________________ TestDeriveView.test_as_instance_requestonly __________________\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_as_instance_requestonly>\n\n    def test_as_instance_requestonly(self):\n        response = DummyResponse()\n        class View:\n            def __call__(self, request):\n                return response\n        view = View()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n>       self.assertTrue('test_viewderivers' in result.__name__)\nE       AssertionError: False is not true\n\nr2e_tests/test_1.py:361: AssertionError\n______________ TestDeriveView.test_function_returns_non_adaptable ______________\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_function_returns_non_adaptable>\n\n    def test_function_returns_non_adaptable(self):\n        def view(request):\n            return None\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n>           result(None, None)\n\nr2e_tests/test_1.py:44: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None, request = None\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable function r2e_tests.test_1.view into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_function_returns_non_adaptable>\n\n    def test_function_returns_non_adaptable(self):\n        def view(request):\n            return None\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n>           self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable function '\n                'pyramid.tests.test_viewderivers.view into a response '\n                'object. The value returned was None. You may have forgotten '\n                'to return a value from the view callable.'\n                )\nE           AssertionError: 'Coul[52 chars]tion r2e_tests.test_1.view into a response obj[94 chars]ble.' != 'Coul[52 chars]tion pyramid.tests.test_viewderivers.view into[109 chars]ble.'\nE           - Could not convert return value of the view callable function r2e_tests.test_1.view into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\nE           ?                                                              ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^\nE           + Could not convert return value of the view callable function pyramid.tests.test_viewderivers.view into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\nE           ?                                                              ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^\n\nr2e_tests/test_1.py:46: AssertionError\n___________ TestDeriveView.test_function_returns_non_adaptable_dict ____________\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_function_returns_non_adaptable_dict>\n\n    def test_function_returns_non_adaptable_dict(self):\n        def view(request):\n            return {'a':1}\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n>           result(None, None)\n\nr2e_tests/test_1.py:62: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None, request = None\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable function r2e_tests.test_1.view into a response object. The value returned was {'a': 1}. You may have forgotten to define a renderer in the view configuration.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_function_returns_non_adaptable_dict>\n\n    def test_function_returns_non_adaptable_dict(self):\n        def view(request):\n            return {'a':1}\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n>           self.assertEqual(\n                e.args[0],\n                \"Could not convert return value of the view callable function \"\n                \"pyramid.tests.test_viewderivers.view into a response \"\n                \"object. The value returned was {'a': 1}. You may have \"\n                \"forgotten to define a renderer in the view configuration.\"\n                )\nE           AssertionError: \"Coul[52 chars]tion r2e_tests.test_1.view into a response obj[104 chars]ion.\" != \"Coul[52 chars]tion pyramid.tests.test_viewderivers.view into[119 chars]ion.\"\nE           Diff is 641 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_1.py:64: AssertionError\n______________ TestDeriveView.test_instance_returns_non_adaptable ______________\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_instance_returns_non_adaptable>\n\n    def test_instance_returns_non_adaptable(self):\n        class AView(object):\n            def __call__(self, request):\n                return None\n        view = AView()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n>           result(None, None)\n\nr2e_tests/test_1.py:82: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None, request = None\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable object <r2e_tests.test_1.TestDeriveView.test_instance_returns_non_adaptable.<locals>.AView object at 0x725891f21ee0> into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_instance_returns_non_adaptable>\n\n    def test_instance_returns_non_adaptable(self):\n        class AView(object):\n            def __call__(self, request):\n                return None\n        view = AView()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            msg = e.args[0]\n>           self.assertTrue(msg.startswith(\n                'Could not convert return value of the view callable object '\n                '<pyramid.tests.test_viewderivers.'))\nE           AssertionError: False is not true\n\nr2e_tests/test_1.py:85: AssertionError\n_____ TestDeriveView.test_requestonly_default_method_returns_non_adaptable _____\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_requestonly_default_method_returns_non_adaptable>\n\n    def test_requestonly_default_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return None\n        result = self.config.derive_view(AView)\n        self.assertFalse(result is AView)\n        try:\n>           result(None, request)\n\nr2e_tests/test_1.py:125: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None\nrequest = <r2e_tests.test_1.DummyRequest object at 0x725891ed06d0>\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable method __call__ of class r2e_tests.test_1.AView into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_requestonly_default_method_returns_non_adaptable>\n\n    def test_requestonly_default_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return None\n        result = self.config.derive_view(AView)\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n>           self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method __call__ of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\nE           AssertionError: 'Coul[68 chars]lass r2e_tests.test_1.AView into a response ob[95 chars]ble.' != 'Coul[68 chars]lass pyramid.tests.test_viewderivers.AView int[110 chars]ble.'\nE           Diff is 663 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_1.py:127: AssertionError\n___ TestDeriveView.test_requestonly_nondefault_method_returns_non_adaptable ____\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_requestonly_nondefault_method_returns_non_adaptable>\n\n    def test_requestonly_nondefault_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def theviewmethod(self):\n                return None\n        result = self.config.derive_view(AView, attr='theviewmethod')\n        self.assertFalse(result is AView)\n        try:\n>           result(None, request)\n\nr2e_tests/test_1.py:148: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None\nrequest = <r2e_tests.test_1.DummyRequest object at 0x725891ec3ac0>\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable method theviewmethod of class r2e_tests.test_1.AView into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_requestonly_nondefault_method_returns_non_adaptable>\n\n    def test_requestonly_nondefault_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def theviewmethod(self):\n                return None\n        result = self.config.derive_view(AView, attr='theviewmethod')\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n>           self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method theviewmethod of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\nE           AssertionError: 'Coul[73 chars]lass r2e_tests.test_1.AView into a response ob[95 chars]ble.' != 'Coul[73 chars]lass pyramid.tests.test_viewderivers.AView int[110 chars]ble.'\nE           Diff is 683 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_1.py:150: AssertionError\n__ AdaptersConfiguratorMixinTests.test_add_resource_url_adapter_dotted_names ___\n\nself = <r2e_tests.test_config.test_adapters.AdaptersConfiguratorMixinTests testMethod=test_add_resource_url_adapter_dotted_names>\n\n    def test_add_resource_url_adapter_dotted_names(self):\n        from pyramid.interfaces import IResourceURL\n        config = self._makeOne(autocommit=True)\n        config.add_resource_url_adapter(\n            'pyramid.tests.test_config.test_adapters.DummyResourceURL',\n            'pyramid.tests.test_config.test_adapters.DummyIface',\n            )\n        iface = DummyIface()\n>       adapter = config.registry.getMultiAdapter((iface, iface),\n                                                    IResourceURL)\n\nr2e_tests/test_config/test_adapters.py:280: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Registry r2e_tests.test_config>\nobjects = (<r2e_tests.test_config.test_adapters.DummyIface object at 0x725891ed7940>, <r2e_tests.test_config.test_adapters.DummyIface object at 0x725891ed7940>)\ninterface = <InterfaceClass pyramid.interfaces.IResourceURL>, name = ''\n\n    def getMultiAdapter(self, objects, interface, name=''):\n        adapter = self.adapters.queryMultiAdapter(objects, interface, name)\n        if adapter is None:\n>           raise ComponentLookupError(objects, interface, name)\nE           zope.interface.interfaces.ComponentLookupError: ((<r2e_tests.test_config.test_adapters.DummyIface object at 0x725891ed7940>, <r2e_tests.test_config.test_adapters.DummyIface object at 0x725891ed7940>), <InterfaceClass pyramid.interfaces.IResourceURL>, '')\n\n.venv/lib/python3.8/site-packages/zope/interface/registry.py:379: ComponentLookupError\n_ AdaptersConfiguratorMixinTests.test_add_resource_url_adapter_introspectables _\n\nself = <r2e_tests.test_config.test_adapters.AdaptersConfiguratorMixinTests testMethod=test_add_resource_url_adapter_introspectables>\n\n    def test_add_resource_url_adapter_introspectables(self):\n        config = self._makeOne()\n        config.add_resource_url_adapter(DummyResourceURL, DummyIface)\n        actions = config.action_state.actions\n        self.assertEqual(len(actions), 1)\n        intrs  = actions[0]['introspectables']\n        self.assertEqual(len(intrs), 1)\n        intr = intrs[0]\n        self.assertEqual(intr.type_name, 'resource url adapter')\n        self.assertEqual(intr.discriminator,\n                         ('resource url adapter', DummyIface))\n        self.assertEqual(intr.category_name, 'resource url adapters')\n>       self.assertEqual(\n            intr.title,\n            \"resource url adapter for resource iface \"\n            \"<class 'pyramid.tests.test_config.test_adapters.DummyIface'>\"\n            )\nE       AssertionError: \"reso[34 chars]e <class 'r2e_tests.test_config.test_adapters.DummyIface'>\" != \"reso[34 chars]e <class 'pyramid.tests.test_config.test_adapters.DummyIface'>\"\nE       - resource url adapter for resource iface <class 'r2e_tests.test_config.test_adapters.DummyIface'>\nE       ?                                                  ^^^\nE       + resource url adapter for resource iface <class 'pyramid.tests.test_config.test_adapters.DummyIface'>\nE       ?                                                 ++ ^^^^^\n\nr2e_tests/test_config/test_adapters.py:326: AssertionError\n________ AdaptersConfiguratorMixinTests.test_add_traverser_dotted_names ________\n\nself = <r2e_tests.test_config.test_adapters.AdaptersConfiguratorMixinTests testMethod=test_add_traverser_dotted_names>\n\n    def test_add_traverser_dotted_names(self):\n        from pyramid.interfaces import ITraverser\n        config = self._makeOne(autocommit=True)\n        config.add_traverser(\n            'pyramid.tests.test_config.test_adapters.DummyTraverser',\n            'pyramid.tests.test_config.test_adapters.DummyIface')\n        iface = DummyIface()\n>       traverser = config.registry.getAdapter(iface, ITraverser)\n\nr2e_tests/test_config/test_adapters.py:237: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Registry r2e_tests.test_config>\nobject = <r2e_tests.test_config.test_adapters.DummyIface object at 0x7258920f63d0>\ninterface = <InterfaceClass pyramid.interfaces.ITraverser>, name = ''\n\n    def getAdapter(self, object, interface, name=''):\n        adapter = self.adapters.queryAdapter(object, interface, name)\n        if adapter is None:\n>           raise ComponentLookupError(object, interface, name)\nE           zope.interface.interfaces.ComponentLookupError: (<r2e_tests.test_config.test_adapters.DummyIface object at 0x7258920f63d0>, <InterfaceClass pyramid.interfaces.ITraverser>, '')\n\n.venv/lib/python3.8/site-packages/zope/interface/registry.py:368: ComponentLookupError\n___ TestAssetsConfiguratorMixin.test_override_asset_directory_with_directory ___\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_directory_with_directory>\n\n    def test_override_asset_directory_with_directory(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset:templates/',\n            'pyramid.tests.test_config.pkgs.asset.subpackage:templates/',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, 'templates/')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, 'templates/')\n    \n        resource_name = 'bar.pt'\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:106: AssertionError\n____ TestAssetsConfiguratorMixin.test_override_asset_directory_with_package ____\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_directory_with_package>\n\n    def test_override_asset_directory_with_package(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset:templates/',\n            'pyramid.tests.test_config.pkgs.asset.subpackage',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, 'templates/')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, '')\n    \n        resource_name = 'templates/bar.pt'\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:129: AssertionError\n________ TestAssetsConfiguratorMixin.test_override_asset_file_with_file ________\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_file_with_file>\n\n    def test_override_asset_file_with_file(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset:templates/foo.pt',\n            'pyramid.tests.test_config.pkgs.asset.subpackage:templates/bar.pt',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, 'templates/foo.pt')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, 'templates/bar.pt')\n    \n        resource_name = ''\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:60: AssertionError\n____ TestAssetsConfiguratorMixin.test_override_asset_package_with_directory ____\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_package_with_directory>\n\n    def test_override_asset_package_with_directory(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset',\n            'pyramid.tests.test_config.pkgs.asset.subpackage:templates/',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, '')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, 'templates/')\n    \n        resource_name = 'bar.pt'\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:152: AssertionError\n_____ TestAssetsConfiguratorMixin.test_override_asset_package_with_package _____\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_package_with_package>\n\n    def test_override_asset_package_with_package(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset',\n            'pyramid.tests.test_config.pkgs.asset.subpackage',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, '')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, '')\n    \n        resource_name = 'templates/bar.pt'\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:83: AssertionError\n_________ TestOverrideProvider.test_get_resource_filename_no_overrides _________\n\nself = <r2e_tests.test_config.test_assets.TestOverrideProvider testMethod=test_get_resource_filename_no_overrides>\n\n    def test_get_resource_filename_no_overrides(self):\n        resource_name = 'test_assets.py'\n        import pyramid.tests.test_config\n        provider = self._makeOne(pyramid.tests.test_config)\n        expected = os.path.join(here, resource_name)\n        result = provider.get_resource_filename(None, resource_name)\n>       self.assertEqual(result, expected)\nE       AssertionError: '/hom[73 chars]faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py' != '/hom[73 chars]faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:297: AssertionError\n____ TestOverrideProvider.test_get_resource_filename_override_returns_None _____\n\nself = <r2e_tests.test_config.test_assets.TestOverrideProvider testMethod=test_get_resource_filename_override_returns_None>\n\n    def test_get_resource_filename_override_returns_None(self):\n        overrides = DummyOverrides(None)\n        self._registerOverrides(overrides)\n        resource_name = 'test_assets.py'\n        import pyramid.tests.test_config\n        provider = self._makeOne(pyramid.tests.test_config)\n        expected = os.path.join(here, resource_name)\n        result = provider.get_resource_filename(None, resource_name)\n>       self.assertEqual(result, expected)\nE       AssertionError: '/hom[73 chars]faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py' != '/hom[73 chars]faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:345: AssertionError\n___________________ TestPackageAssetSource.test_get_filename ___________________\n\nself = <r2e_tests.test_config.test_assets.TestPackageAssetSource testMethod=test_get_filename>\n\n    def test_get_filename(self):\n        source = self._makeOne('')\n>       self.assertEqual(source.get_filename('test_assets.py'),\n                         os.path.join(here, 'test_assets.py'))\nE       AssertionError: '/hom[73 chars]faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py' != '/hom[73 chars]faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:716: AssertionError\n_____________ TestPackageAssetSource.test_get_filename_with_prefix _____________\n\nself = <r2e_tests.test_config.test_assets.TestPackageAssetSource testMethod=test_get_filename_with_prefix>\n\n    def test_get_filename_with_prefix(self):\n        source = self._makeOne('test_assets.py')\n>       self.assertEqual(source.get_filename(''),\n                         os.path.join(here, 'test_assets.py'))\nE       AssertionError: '/hom[73 chars]faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py' != '/hom[73 chars]faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:721: AssertionError\n_________ TestI18NConfiguratorMixin.test_add_translation_dirs_abspath __________\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_abspath>\n\n    def test_add_translation_dirs_abspath(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n>       config.add_translation_dirs(locale)\n\nr2e_tests/test_config/test_i18n.py:86: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \npyramid/util.py:573: in wrapper\n    result = wrapped(self, *arg, **kw)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <pyramid.config.Configurator object at 0x725892613a60>\nspecs = ('/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale',)\nintrospectables = []\nspec = '/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale'\npackage_name = None\n\n    @action_method\n    def add_translation_dirs(self, *specs):\n        \"\"\" Add one or more :term:`translation directory` paths to the\n        current configuration state.  The ``specs`` argument is a\n        sequence that may contain absolute directory paths\n        (e.g. ``/usr/share/locale``) or :term:`asset specification`\n        names naming a directory path (e.g. ``some.package:locale``)\n        or a combination of the two.\n    \n        Example:\n    \n        .. code-block:: python\n    \n           config.add_translation_dirs('/usr/share/locale',\n                                       'some.package:locale')\n    \n        Later calls to ``add_translation_dir`` insert directories into the\n        beginning of the list of translation directories created by earlier\n        calls.  This means that the same translation found in a directory\n        added later in the configuration process will be found before one\n        added earlier in the configuration process.  However, if multiple\n        specs are provided in a single call to ``add_translation_dirs``, the\n        directories will be inserted into the beginning of the directory list\n        in the order they're provided in the ``*specs`` list argument (items\n        earlier in the list trump ones later in the list).\n        \"\"\"\n        directories = []\n        introspectables = []\n    \n        for spec in specs[::-1]: # reversed\n            package_name, filename = self._split_spec(spec)\n            if package_name is None: # absolute filename\n                directory = filename\n            else:\n                __import__(package_name)\n                package = sys.modules[package_name]\n                directory = os.path.join(package_path(package), filename)\n    \n            if not os.path.isdir(os.path.realpath(directory)):\n>               raise ConfigurationError('\"%s\" is not a directory' %\n                                         directory)\nE               pyramid.exceptions.ConfigurationError: \"/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale\" is not a directory\n\npyramid/config/i18n.py:86: ConfigurationError\n________ TestI18NConfiguratorMixin.test_add_translation_dirs_asset_spec ________\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_asset_spec>\n\n    def test_add_translation_dirs_asset_spec(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale')\n>       self.assertEqual(config.registry.getUtility(ITranslationDirectories),\n                         [locale])\nE       AssertionError: Lists differ: ['/ho[70 chars]c5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale'] != ['/ho[70 chars]c5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale']\nE       \nE       First differing element 0:\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale'\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale'\nE       \nE       - ['/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale']\nE       ?                                                                                                      -- ^^^^^\nE       \nE       + ['/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale']\nE       ?                                                                                                       ^^^\n\nr2e_tests/test_config/test_i18n.py:54: AssertionError\n_ TestI18NConfiguratorMixin.test_add_translation_dirs_asset_spec_existing_translation_dirs _\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_asset_spec_existing_translation_dirs>\n\n    def test_add_translation_dirs_asset_spec_existing_translation_dirs(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n        directories = ['abc']\n        config.registry.registerUtility(directories, ITranslationDirectories)\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale')\n        result = config.registry.getUtility(ITranslationDirectories)\n>       self.assertEqual(result, [locale, 'abc'])\nE       AssertionError: Lists differ: ['/ho[77 chars]afa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale', 'abc'] != ['/ho[77 chars]afa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale', 'abc']\nE       \nE       First differing element 0:\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale'\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale'\nE       \nE       - ['/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale',\nE       ?                                                                                                      -- ^^^^^\nE       \nE       + ['/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale',\nE       ?                                                                                                       ^^^\nE       \nE          'abc']\n\nr2e_tests/test_config/test_i18n.py:64: AssertionError\n______ TestI18NConfiguratorMixin.test_add_translation_dirs_multiple_specs ______\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_multiple_specs>\n\n    def test_add_translation_dirs_multiple_specs(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale',\n                                    'pyramid.tests.pkgs.localeapp:locale2')\n>       self.assertEqual(config.registry.getUtility(ITranslationDirectories),\n                         [locale, locale2])\nE       AssertionError: Lists differ: ['/ho[91 chars]d31f/pyramid/tests/pkgs/localeapp/locale', '/h[130 chars]le2'] != ['/ho[91 chars]d31f/r2e_tests/pkgs/localeapp/locale', '/home/[122 chars]le2']\nE       \nE       First differing element 0:\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale'\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale'\nE       \nE       Diff is 1002 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_config/test_i18n.py:71: AssertionError\n_ TestI18NConfiguratorMixin.test_add_translation_dirs_multiple_specs_multiple_calls _\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_multiple_specs_multiple_calls>\n\n    def test_add_translation_dirs_multiple_specs_multiple_calls(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale',\n                                    'pyramid.tests.pkgs.localeapp:locale2')\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale3')\n>       self.assertEqual(config.registry.getUtility(ITranslationDirectories),\n                         [locale3, locale, locale2])\nE       AssertionError: Lists differ: ['/ho[91 chars]d31f/pyramid/tests/pkgs/localeapp/locale3', '/[269 chars]le2'] != ['/ho[91 chars]d31f/r2e_tests/pkgs/localeapp/locale3', '/home[257 chars]le2']\nE       \nE       First differing element 0:\nE       '/hom[69 chars]c5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale3'\nE       '/hom[69 chars]c5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale3'\nE       \nE       Diff is 1504 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_config/test_i18n.py:80: AssertionError\n___________________ ConfiguratorTests.test_ctor_no_registry ____________________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_ctor_no_registry>\n\n    def test_ctor_no_registry(self):\n        import sys\n        from pyramid.interfaces import ISettings\n        from pyramid.config import Configurator\n        from pyramid.interfaces import IRendererFactory\n        config = Configurator()\n        this_pkg = sys.modules['pyramid.tests.test_config']\n        self.assertTrue(config.registry.getUtility(ISettings))\n>       self.assertEqual(config.package, this_pkg)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:68: AssertionError\n_________ ConfiguratorTests.test_ctor_noreg_debug_logger_None_default __________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_ctor_noreg_debug_logger_None_default>\n\n    def test_ctor_noreg_debug_logger_None_default(self):\n        from pyramid.interfaces import IDebugLogger\n        config = self._makeOne()\n        logger = config.registry.getUtility(IDebugLogger)\n>       self.assertEqual(logger.name, 'pyramid.tests.test_config')\nE       AssertionError: 'r2e_tests.test_config' != 'pyramid.tests.test_config'\nE       - r2e_tests.test_config\nE       ?  ^^^\nE       + pyramid.tests.test_config\nE       ? ++ ^^^^^\n\nr2e_tests/test_config/test_init.py:124: AssertionError\n_____________ ConfiguratorTests.test_include_constant_root_package _____________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_include_constant_root_package>\n\n    def test_include_constant_root_package(self):\n        from pyramid import tests\n        from pyramid.tests import test_config\n        config = self._makeOne(root_package=tests)\n        results = {}\n        def include(config):\n            results['package'] = config.package\n            results['root_package'] = config.root_package\n        config.include(include)\n        self.assertEqual(results['root_package'], tests)\n>       self.assertEqual(results['package'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:777: AssertionError\n_______________ ConfiguratorTests.test_scan_integration_conflict _______________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_scan_integration_conflict>\n\n    def test_scan_integration_conflict(self):\n        from pyramid.tests.test_config.pkgs import selfscan\n        from pyramid.config import Configurator\n        c = Configurator()\n        c.scan(selfscan)\n        c.scan(selfscan)\n        try:\n>           c.commit()\n\nr2e_tests/test_config/test_init.py:1039: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \npyramid/config/__init__.py:654: in commit\n    self.action_state.execute_actions(introspector=self.introspector)\npyramid/config/__init__.py:1163: in execute_actions\n    action = next(pending_actions, None)\npyramid/config/__init__.py:1121: in resume\n    for a, b in zip_longest(actions, executed_actions):\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nactions = [{'args': (), 'callable': <function ViewsConfiguratorMixin.add_view.<locals>.register at 0x725892038790>, 'discriminat...5892038ca0>, 'discriminator': ('view', None, 'two', None, 'd41d8cd98f00b204e9800998ecf8427e'), 'includepath': (), ...}]\n\n    def resolveConflicts(actions):\n        \"\"\"Resolve conflicting actions\n    \n        Given an actions list, identify and try to resolve conflicting actions.\n        Actions conflict if they have the same non-None discriminator.\n        Conflicting actions can be resolved if the include path of one of\n        the actions is a prefix of the includepaths of the other\n        conflicting actions and is unequal to the include paths in the\n        other conflicting actions.\n        \"\"\"\n    \n        def orderandpos(v):\n            n, v = v\n            if not isinstance(v, dict):\n                # old-style tuple action\n                v = expand_action(*v)\n            return (v['order'] or 0, n)\n    \n        sactions = sorted(enumerate(actions), key=orderandpos)\n    \n        def orderonly(v):\n            n, v = v\n            if not isinstance(v, dict):\n                # old-style tuple action\n                v = expand_action(*v)\n            return v['order'] or 0\n    \n        for order, actiongroup in itertools.groupby(sactions, orderonly):\n            # \"order\" is an integer grouping. Actions in a lower order will be\n            # executed before actions in a higher order.  All of the actions in\n            # one grouping will be executed (its callable, if any will be called)\n            # before any of the actions in the next.\n    \n            unique = {}\n            output = []\n    \n            for i, action in actiongroup:\n                # Within an order, actions are executed sequentially based on\n                # original action ordering (\"i\").\n    \n                if not isinstance(action, dict):\n                    # old-style tuple action\n                    action = expand_action(*action)\n    \n                # \"ainfo\" is a tuple of (order, i, action) where \"order\" is a\n                # user-supplied grouping, \"i\" is an integer expressing the relative\n                # position of this action in the action list being resolved, and\n                # \"action\" is an action dictionary.  The purpose of an ainfo is to\n                # associate an \"order\" and an \"i\" with a particular action; \"order\"\n                # and \"i\" exist for sorting purposes after conflict resolution.\n                ainfo = (order, i, action)\n    \n                discriminator = undefer(action['discriminator'])\n                action['discriminator'] = discriminator\n    \n                if discriminator is None:\n                    # The discriminator is None, so this action can never conflict.\n                    # We can add it directly to the result.\n                    output.append(ainfo)\n                    continue\n    \n                L = unique.setdefault(discriminator, [])\n                L.append(ainfo)\n    \n            # Check for conflicts\n            conflicts = {}\n    \n            for discriminator, ainfos in unique.items():\n                # We use (includepath, order, i) as a sort key because we need to\n                # sort the actions by the paths so that the shortest path with a\n                # given prefix comes first.  The \"first\" action is the one with the\n                # shortest include path.  We break sorting ties using \"order\", then\n                # \"i\".\n                def bypath(ainfo):\n                    path, order, i = ainfo[2]['includepath'], ainfo[0], ainfo[1]\n                    return path, order, i\n    \n                ainfos.sort(key=bypath)\n                ainfo, rest = ainfos[0], ainfos[1:]\n                output.append(ainfo)\n                _, _, action = ainfo\n                basepath, baseinfo, discriminator = (\n                    action['includepath'],\n                    action['info'],\n                    action['discriminator'],\n                    )\n    \n                for _, _, action in rest:\n                    includepath = action['includepath']\n                    # Test whether path is a prefix of opath\n                    if (includepath[:len(basepath)] != basepath or  # not a prefix\n                            includepath == basepath):\n                        L = conflicts.setdefault(discriminator, [baseinfo])\n                        L.append(action['info'])\n    \n            if conflicts:\n>               raise ConfigurationConflictError(conflicts)\nE               pyramid.exceptions.ConfigurationConflictError: Conflicting configuration actions\nE                 For: ('view', None, '', None, 'd41d8cd98f00b204e9800998ecf8427e')\nE                   Line 4 of file /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/selfscan/__init__.py:\nE                       def abc(request):\nE                   Line 4 of file /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/selfscan/__init__.py:\nE                       def abc(request):\nE                 For: ('view', None, 'two', None, 'd41d8cd98f00b204e9800998ecf8427e')\nE                   Line 4 of file /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/selfscan/another.py:\nE                       def two(request):\nE                   Line 4 of file /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/selfscan/another.py:\nE                       def two(request):\n\npyramid/config/__init__.py:1299: ConfigurationConflictError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_scan_integration_conflict>\n\n    def test_scan_integration_conflict(self):\n        from pyramid.tests.test_config.pkgs import selfscan\n        from pyramid.config import Configurator\n        c = Configurator()\n        c.scan(selfscan)\n        c.scan(selfscan)\n        try:\n            c.commit()\n        except ConfigurationConflictError as why:\n            def scanconflicts(e):\n                conflicts = e._conflicts.values()\n                for conflict in conflicts:\n                    for confinst in conflict:\n                        yield confinst.src\n            which = list(scanconflicts(why))\n            self.assertEqual(len(which), 4)\n>           self.assertTrue(\"@view_config(renderer='string')\" in which)\nE           AssertionError: False is not true\n\nr2e_tests/test_config/test_init.py:1048: AssertionError\n_______ ConfiguratorTests.test_setup_registry_debug_logger_None_default ________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_setup_registry_debug_logger_None_default>\n\n    def test_setup_registry_debug_logger_None_default(self):\n        from pyramid.registry import Registry\n        from pyramid.interfaces import IDebugLogger\n        reg = Registry()\n        config = self._makeOne(reg)\n        config.setup_registry()\n        logger = reg.getUtility(IDebugLogger)\n>       self.assertEqual(logger.name, 'pyramid.tests.test_config')\nE       AssertionError: 'r2e_tests.test_config' != 'pyramid.tests.test_config'\nE       - r2e_tests.test_config\nE       ?  ^^^\nE       + pyramid.tests.test_config\nE       ? ++ ^^^^^\n\nr2e_tests/test_config/test_init.py:444: AssertionError\n____ TestConfigurator_add_directive.test_add_directive_with_custom_callable ____\n\nself = <r2e_tests.test_config.test_init.TestConfigurator_add_directive testMethod=test_add_directive_with_custom_callable>\n\n    def test_add_directive_with_custom_callable(self):\n        from pyramid.tests import test_config\n        config = self.config\n        config.add_directive(\n                'dummy_callable', 'pyramid.tests.test_config.dummy_callable')\n        self.assertTrue(hasattr(config, 'dummy_callable'))\n        config.dummy_callable('discrim')\n        after = config.action_state\n        action = after.actions[-1]\n        self.assertEqual(action['discriminator'], 'discrim')\n        self.assertEqual(action['callable'], None)\n>       self.assertEqual(action['args'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:1247: AssertionError\n________ TestConfigurator_add_directive.test_add_directive_with_partial ________\n\nself = <r2e_tests.test_config.test_init.TestConfigurator_add_directive testMethod=test_add_directive_with_partial>\n\n    def test_add_directive_with_partial(self):\n        from pyramid.tests import test_config\n        config = self.config\n        config.add_directive(\n                'dummy_partial', 'pyramid.tests.test_config.dummy_partial')\n        self.assertTrue(hasattr(config, 'dummy_partial'))\n        config.dummy_partial()\n        after = config.action_state\n        action = after.actions[-1]\n        self.assertEqual(action['discriminator'], 'partial')\n        self.assertEqual(action['callable'], None)\n>       self.assertEqual(action['args'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:1234: AssertionError\n_________ TestConfigurator_add_directive.test_extend_with_dotted_name __________\n\nself = <r2e_tests.test_config.test_init.TestConfigurator_add_directive testMethod=test_extend_with_dotted_name>\n\n    def test_extend_with_dotted_name(self):\n        from pyramid.tests import test_config\n        config = self.config\n        config.add_directive(\n            'dummy_extend', 'pyramid.tests.test_config.dummy_extend')\n        self.assertTrue(hasattr(config, 'dummy_extend'))\n        config.dummy_extend('discrim')\n        after = config.action_state\n        action = after.actions[-1]\n        self.assertEqual(action['discriminator'], 'discrim')\n        self.assertEqual(action['callable'], None)\n>       self.assertEqual(action['args'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:1221: AssertionError\n_______ TestConfigurator_add_directive.test_extend_with_python_callable ________\n\nself = <r2e_tests.test_config.test_init.TestConfigurator_add_directive testMethod=test_extend_with_python_callable>\n\n    def test_extend_with_python_callable(self):\n        from pyramid.tests import test_config\n        config = self.config\n        config.add_directive(\n            'dummy_extend', dummy_extend)\n        self.assertTrue(hasattr(config, 'dummy_extend'))\n        config.dummy_extend('discrim')\n        after = config.action_state\n        action = after.actions[-1]\n        self.assertEqual(action['discriminator'], 'discrim')\n        self.assertEqual(action['callable'], None)\n>       self.assertEqual(action['args'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:1260: AssertionError\n_________ TestConfigurator__add_predicate.test_factory_as_dotted_name __________\n\nself = <r2e_tests.test_config.test_init.TestConfigurator__add_predicate testMethod=test_factory_as_dotted_name>\n\n    def test_factory_as_dotted_name(self):\n        config = self._makeOne()\n    \n        def _fakeAction(discriminator, callable=None, args=(),\n                        kw=None, order=0, introspectables=(), **extra):\n            self.assertEqual(len(introspectables), 1)\n            self.assertEqual(introspectables[0]['name'], 'testing')\n            self.assertEqual(introspectables[0]['factory'], DummyPredicate)\n    \n        config.action = _fakeAction\n>       config._add_predicate(\n            'route',\n            'testing',\n            'pyramid.tests.test_config.test_init.DummyPredicate'\n            )\n\nr2e_tests/test_config/test_init.py:1324: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \npyramid/config/__init__.py:543: in _add_predicate\n    self.action(discriminator, register, introspectables=(intr,),\nr2e_tests/test_config/test_init.py:1321: in _fakeAction\n    self.assertEqual(introspectables[0]['factory'], DummyPredicate)\nE   AssertionError: <class 'pyramid.tests.test_config.test_init.DummyPredicate'> != <class 'r2e_tests.test_config.test_init.DummyPredicate'>\n____ TestViewsConfigurationMixin.test_add_static_view_package_here_relative ____\n\nself = <r2e_tests.test_config.test_views.TestViewsConfigurationMixin testMethod=test_add_static_view_package_here_relative>\n\n    def test_add_static_view_package_here_relative(self):\n        from pyramid.interfaces import IStaticURLInfo\n        info = DummyStaticURLInfo()\n        config = self._makeOne(autocommit=True)\n        config.registry.registerUtility(info, IStaticURLInfo)\n        config.add_static_view('static', 'files')\n>       self.assertEqual(\n            info.added,\n            [(config, 'static', 'pyramid.tests.test_config:files', {})])\nE       AssertionError: Lists differ: [(<py[39 chars]258921730d0>, 'static', 'r2e_tests.test_config:files', {})] != [(<py[39 chars]258921730d0>, 'static', 'pyramid.tests.test_config:files', {})]\nE       \nE       First differing element 0:\nE       (<pyr[37 chars]7258921730d0>, 'static', 'r2e_tests.test_config:files', {})\nE       (<pyr[37 chars]7258921730d0>, 'static', 'pyramid.tests.test_config:files', {})\nE       \nE         [(<pyramid.config.Configurator object at 0x7258921730d0>,\nE           'static',\nE       -   'r2e_tests.test_config:files',\nE       ?     ^^^\nE       \nE       +   'pyramid.tests.test_config:files',\nE       ?    ++ ^^^^^\nE       \nE           {})]\n\nr2e_tests/test_config/test_views.py:1842: AssertionError\n_______ TestViewsConfigurationMixin.test_add_view_with_template_renderer _______\n\nself = <r2e_tests.test_config.test_views.TestViewsConfigurationMixin testMethod=test_add_view_with_template_renderer>\n\n    def test_add_view_with_template_renderer(self):\n        from pyramid.tests import test_config\n        from pyramid.interfaces import ISettings\n        class view(object):\n            def __init__(self, context, request):\n                self.request = request\n                self.context = context\n    \n            def __call__(self):\n                return {'a':'1'}\n        config = self._makeOne(autocommit=True)\n        renderer = self._registerRenderer(config)\n        fixture = 'pyramid.tests.test_config:files/minimal.txt'\n        config.introspection = False\n        config.add_view(view=view, renderer=fixture)\n        wrapper = self._getViewCallable(config)\n        request = self._makeRequest(config)\n        result = wrapper(None, request)\n        self.assertEqual(result.body, b'Hello!')\n        settings = config.registry.queryUtility(ISettings)\n        result = renderer.info\n        self.assertEqual(result.registry, config.registry)\n        self.assertEqual(result.type, '.txt')\n>       self.assertEqual(result.package, test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_views.py:1143: AssertionError\n_ TestViewsConfigurationMixin.test_add_view_with_template_renderer_no_callable _\n\nself = <r2e_tests.test_config.test_views.TestViewsConfigurationMixin testMethod=test_add_view_with_template_renderer_no_callable>\n\n    def test_add_view_with_template_renderer_no_callable(self):\n        from pyramid.tests import test_config\n        from pyramid.interfaces import ISettings\n        config = self._makeOne(autocommit=True)\n        renderer = self._registerRenderer(config)\n        fixture = 'pyramid.tests.test_config:files/minimal.txt'\n        config.introspection = False\n        config.add_view(view=None, renderer=fixture)\n        wrapper = self._getViewCallable(config)\n        request = self._makeRequest(config)\n        result = wrapper(None, request)\n        self.assertEqual(result.body, b'Hello!')\n        settings = config.registry.queryUtility(ISettings)\n        result = renderer.info\n        self.assertEqual(result.registry, config.registry)\n        self.assertEqual(result.type, '.txt')\n>       self.assertEqual(result.package, test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_views.py:1184: AssertionError\n_________ TestStaticURLInfo.test_generate_url_cachebust_with_overrides _________\n\nself = <r2e_tests.test_config.test_views.TestStaticURLInfo testMethod=test_generate_url_cachebust_with_overrides>\n\n    def test_generate_url_cachebust_with_overrides(self):\n        config = testing.setUp()\n        try:\n            request = testing.DummyRequest()\n            config.add_static_view('static', 'path')\n            config.override_asset(\n                'pyramid.tests.test_config:path/',\n                'pyramid.tests.test_config:other_path/')\n            def cb(val):\n                def cb_(request, subpath, kw):\n                    kw['_query'] = {'x': val}\n                    return subpath, kw\n                return cb_\n            config.add_cache_buster('path', cb('foo'))\n            result = request.static_url('path/foo.png')\n            self.assertEqual(result, 'http://example.com/static/foo.png?x=foo')\n            config.add_cache_buster('other_path', cb('bar'), explicit=True)\n            result = request.static_url('path/foo.png')\n>           self.assertEqual(result, 'http://example.com/static/foo.png?x=bar')\nE           AssertionError: 'http://example.com/static/foo.png?x=foo' != 'http://example.com/static/foo.png?x=bar'\nE           - http://example.com/static/foo.png?x=foo\nE           ?                                     ^^^\nE           + http://example.com/static/foo.png?x=bar\nE           ?                                     ^^^\n\nr2e_tests/test_config/test_views.py:2921: AssertionError\n___________________ Test_view_description.test_without_text ____________________\n\nself = <r2e_tests.test_config.test_views.Test_view_description testMethod=test_without_text>\n\n    def test_without_text(self):\n        def view(): pass\n        result = self._callFUT(view)\n>       self.assertEqual(result,\n                         'function pyramid.tests.test_config.test_views.view')\nE       AssertionError: 'function r2e_tests.test_config.test_views.view' != 'function pyramid.tests.test_config.test_views.view'\nE       - function r2e_tests.test_config.test_views.view\nE       ?           ^^^\nE       + function pyramid.tests.test_config.test_views.view\nE       ?          ++ ^^^^^\n\nr2e_tests/test_config/test_views.py:3092: AssertionError\n_______________ TestPRequestCommand.test_command_display_headers _______________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_display_headers>\n\n    def test_command_display_headers(self):\n        command = self._makeOne(\n            ['', '--display-headers', 'development.ini', '/'])\n        command.run()\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(\n            self._out,\n            ['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc'])\nE       AssertionError: Lists differ: ['200 OK', b'abc'] != ['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc']\nE       \nE       First differing element 1:\nE       b'abc'\nE       'Content-Type: text/html; charset=UTF-8'\nE       \nE       Second list contains 1 additional elements.\nE       First extra element 2:\nE       'abc'\nE       \nE       - ['200 OK', b'abc']\nE       + ['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc']\n\nr2e_tests/test_scripts/test_prequest.py:202: AssertionError\n_________ TestPRequestCommand.test_command_has_content_type_header_var _________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_has_content_type_header_var>\n\n    def test_command_has_content_type_header_var(self):\n        command = self._makeOne(\n            ['', '--header=content-type:app/foo','development.ini', '/'])\n        command.run()\n        self.assertEqual(self._environ['CONTENT_TYPE'], 'app/foo')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:92: AssertionError\n_____________ TestPRequestCommand.test_command_has_good_header_var _____________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_has_good_header_var>\n\n    def test_command_has_good_header_var(self):\n        command = self._makeOne(\n            ['', '--header=name:value','development.ini', '/'])\n        command.run()\n        self.assertEqual(self._environ['HTTP_NAME'], 'value')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:69: AssertionError\n__________ TestPRequestCommand.test_command_has_multiple_header_vars ___________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_has_multiple_header_vars>\n\n    def test_command_has_multiple_header_vars(self):\n        command = self._makeOne(\n            ['',\n             '--header=name:value',\n             '--header=name2:value2',\n             'development.ini',\n             '/'])\n        command.run()\n        self.assertEqual(self._environ['HTTP_NAME'], 'value')\n        self.assertEqual(self._environ['HTTP_NAME2'], 'value2')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:107: AssertionError\n_________________ TestPRequestCommand.test_command_method_get __________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_get>\n\n    def test_command_method_get(self):\n        command = self._makeOne(['', '--method=GET', 'development.ini', '/'])\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'GET')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:116: AssertionError\n_______________ TestPRequestCommand.test_command_method_options ________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_options>\n\n    def test_command_method_options(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=OPTIONS', 'development.ini',\n                                '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'OPTIONS')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:184: AssertionError\n________________ TestPRequestCommand.test_command_method_patch _________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_patch>\n\n    def test_command_method_patch(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=PATCH', 'development.ini', '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'PATCH')\n        self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')\n        self.assertEqual(self._environ['wsgi.input'], stdin)\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:158: AssertionError\n_________________ TestPRequestCommand.test_command_method_post _________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_post>\n\n    def test_command_method_post(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=POST', 'development.ini', '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'POST')\n        self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')\n        self.assertEqual(self._environ['wsgi.input'], stdin)\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:130: AssertionError\n_______________ TestPRequestCommand.test_command_method_propfind _______________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_propfind>\n\n    def test_command_method_propfind(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=PROPFIND', 'development.ini',\n                                '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'PROPFIND')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:171: AssertionError\n_________________ TestPRequestCommand.test_command_method_put __________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_put>\n\n    def test_command_method_put(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=PUT', 'development.ini', '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'PUT')\n        self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')\n        self.assertEqual(self._environ['wsgi.input'], stdin)\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:144: AssertionError\n________ TestPRequestCommand.test_command_path_doesnt_start_with_slash _________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_path_doesnt_start_with_slash>\n\n    def test_command_path_doesnt_start_with_slash(self):\n        command = self._makeOne(['', 'development.ini', 'abc'])\n        command.run()\n        self.assertEqual(self._path_info, '/abc')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:50: AssertionError\n__________________ TestPRequestCommand.test_command_two_args ___________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_two_args>\n\n    def test_command_two_args(self):\n        command = self._makeOne(['', 'development.ini', '/'])\n        command.run()\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:42: AssertionError\n________________ TestPRequestCommand.test_command_w_basic_auth _________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_w_basic_auth>\n\n    def test_command_w_basic_auth(self):\n        command = self._makeOne(\n            ['', '--login=user:password',\n                 '--header=name:value','development.ini', '/'])\n        command.run()\n        self.assertEqual(self._environ['HTTP_NAME'], 'value')\n        self.assertEqual(self._environ['HTTP_AUTHORIZATION'],\n                        'Basic dXNlcjpwYXNzd29yZA==')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:82: AssertionError\n______________ TestPRequestCommand.test_command_with_query_string ______________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_with_query_string>\n\n    def test_command_with_query_string(self):\n        command = self._makeOne(['', 'development.ini', '/abc?a=1&b=2&c'])\n        command.run()\n        self.assertEqual(self._environ['QUERY_STRING'], 'a=1&b=2&c')\n        self.assertEqual(self._path_info, '/abc')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:193: AssertionError\n_______________ TestPRoutesCommand.test_config_format_ini_commas _______________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_config_format_ini_commas>\n\n    def test_config_format_ini_commas(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n    \n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        config_factory = dummy.DummyConfigParserFactory()\n        command.ConfigParser = config_factory\n        config_factory.items = [('format', 'method,name')]\n    \n        result = command.run()\n>       self.assertEqual(result, 0)\nE       AssertionError: 2 != 0\n\nr2e_tests/test_scripts/test_proutes.py:726: AssertionError\n______________ TestPRoutesCommand.test_config_format_ini_newlines ______________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_config_format_ini_newlines>\n\n    def test_config_format_ini_newlines(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n    \n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        config_factory = dummy.DummyConfigParserFactory()\n        command.ConfigParser = config_factory\n        config_factory.items = [('format', 'method\\nname')]\n    \n        result = command.run()\n>       self.assertEqual(result, 0)\nE       AssertionError: 2 != 0\n\nr2e_tests/test_scripts/test_proutes.py:660: AssertionError\n_______________ TestPRoutesCommand.test_config_format_ini_spaces _______________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_config_format_ini_spaces>\n\n    def test_config_format_ini_spaces(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n    \n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        config_factory = dummy.DummyConfigParserFactory()\n        command.ConfigParser = config_factory\n        config_factory.items = [('format', 'method name')]\n    \n        result = command.run()\n>       self.assertEqual(result, 0)\nE       AssertionError: 2 != 0\n\nr2e_tests/test_scripts/test_proutes.py:693: AssertionError\n_________ TestPRoutesCommand.test_one_route_all_methods_view_only_post _________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_one_route_all_methods_view_only_post>\n\n    def test_one_route_all_methods_view_only_post(self):\n        from pyramid.renderers import null_renderer as nr\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method='POST'\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1', 'POST'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:309: AssertionError\n_________ TestPRoutesCommand.test_one_route_only_post_view_all_methods _________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_one_route_only_post_view_all_methods>\n\n    def test_one_route_only_post_view_all_methods(self):\n        from pyramid.renderers import null_renderer as nr\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b', request_method='POST')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1', 'POST'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:336: AssertionError\n________ TestPRoutesCommand.test_one_route_only_post_view_post_and_get _________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_one_route_only_post_view_post_and_get>\n\n    def test_one_route_only_post_view_post_and_get(self):\n        from pyramid.renderers import null_renderer as nr\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b', request_method='POST')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=('POST', 'GET')\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1', 'POST'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:364: AssertionError\n_____ TestPRoutesCommand.test_one_route_with_long_name_one_view_registered _____\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_one_route_with_long_name_one_view_registered>\n\n    def test_one_route_with_long_name_one_view_registered(self):\n        from zope.interface import Interface\n        from pyramid.interfaces import IRouteRequest\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import IView\n        registry = self._makeRegistry()\n    \n        def view():pass\n    \n        class IMyRoute(Interface):\n            pass\n    \n        registry.registerAdapter(\n            view,\n            (IViewClassifier, IMyRoute, Interface),\n            IView, ''\n        )\n    \n        registry.registerUtility(IMyRoute, IRouteRequest,\n                                 name='very_long_name_123')\n    \n        command = self._makeOne()\n        route = dummy.DummyRoute(\n            'very_long_name_123',\n            '/and_very_long_pattern_as_well'\n        )\n        mapper = dummy.DummyMapper(route)\n        command._get_mapper = lambda *arg: mapper\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()[:3]\n>       self.assertEqual(\n            compare_to,\n            ['very_long_name_123',\n             '/and_very_long_pattern_as_well',\n             'pyramid.tests.test_scripts.test_proutes.view']\n        )\nE       AssertionError: Lists differ: ['ver[36 chars]ttern_as_well', 'r2e_tests.test_scripts.test_proutes.view'] != ['ver[36 chars]ttern_as_well', 'pyramid.tests.test_scripts.test_proutes.view']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view'\nE       'pyramid.tests.test_scripts.test_proutes.view'\nE       \nE         ['very_long_name_123',\nE          '/and_very_long_pattern_as_well',\nE       -  'r2e_tests.test_scripts.test_proutes.view']\nE       ?    ^^^\nE       \nE       +  'pyramid.tests.test_scripts.test_proutes.view']\nE       ?   ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:195: AssertionError\n______ TestPRoutesCommand.test_route_is_get_view_request_method_not_post _______\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_route_is_get_view_request_method_not_post>\n\n    def test_route_is_get_view_request_method_not_post(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b', request_method='GET')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1',\n            'GET'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'GET'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'GET']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'GET']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'GET']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:503: AssertionError\n____________ TestPRoutesCommand.test_route_request_method_mismatch _____________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_route_request_method_mismatch>\n\n    def test_route_request_method_mismatch(self):\n        from pyramid.renderers import null_renderer as nr\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b', request_method='POST')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method='GET'\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1',\n            '<route', 'mismatch>'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1[20 chars]ch>'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.v[24 chars]ch>']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE         ['foo',\nE          '/a/b',\nE       -  'r2e_tests.test_scripts.test_proutes.view1',\nE       ?    ^^^\nE       \nE       +  'pyramid.tests.test_scripts.test_proutes.view1',\nE       ?   ++ ^^^^^\nE       \nE          '<route',\nE          'mismatch>']\n\nr2e_tests/test_scripts/test_proutes.py:393: AssertionError\n__________________ TestPRoutesCommand.test_route_static_views __________________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_route_static_views>\n\n    def test_route_static_views(self):\n        from pyramid.renderers import null_renderer as nr\n        config = self._makeConfig(autocommit=True)\n        config.add_static_view('static', 'static', cache_max_age=3600)\n        config.add_static_view(name='static2', path='/var/www/static')\n        config.add_static_view(\n            name='pyramid_scaffold',\n            path='pyramid:scaffolds/starter/+package+/static'\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 5)\n    \n        expected = [\n            ['__static/', '/static/*subpath',\n             'pyramid.tests.test_scripts:static/', '*'],\n            ['__static2/', '/static2/*subpath', '/var/www/static/', '*'],\n            ['__pyramid_scaffold/', '/pyramid_scaffold/*subpath',\n             'pyramid:scaffolds/starter/+package+/static/',  '*'],\n        ]\n    \n        for index, line in enumerate(L[2:]):\n            data = line.split()\n>           self.assertEqual(data, expected[index])\nE           AssertionError: Lists differ: ['__static/', '/static/*subpath', 'r2e_tests.test_scripts:static/', '*'] != ['__static/', '/static/*subpath', 'pyramid.tests.test_scripts:static/', '*']\nE           \nE           First differing element 2:\nE           'r2e_tests.test_scripts:static/'\nE           'pyramid.tests.test_scripts:static/'\nE           \nE           - ['__static/', '/static/*subpath', 'r2e_tests.test_scripts:static/', '*']\nE           ?                                     ^^^\nE           \nE           + ['__static/', '/static/*subpath', 'pyramid.tests.test_scripts:static/', '*']\nE           ?                                    ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:423: AssertionError\n___________ TestPRoutesCommand.test_single_route_one_view_registered ___________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_single_route_one_view_registered>\n\n    def test_single_route_one_view_registered(self):\n        from zope.interface import Interface\n        from pyramid.interfaces import IRouteRequest\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import IView\n        registry = self._makeRegistry()\n    \n        def view():pass\n        class IMyRoute(Interface):\n            pass\n        registry.registerAdapter(view,\n                                 (IViewClassifier, IMyRoute, Interface),\n                                 IView, '')\n        registry.registerUtility(IMyRoute, IRouteRequest, name='a')\n        command = self._makeOne()\n        route = dummy.DummyRoute('a', '/a')\n        mapper = dummy.DummyMapper(route)\n        command._get_mapper = lambda *arg: mapper\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()[:3]\n>       self.assertEqual(\n            compare_to,\n            ['a', '/a', 'pyramid.tests.test_scripts.test_proutes.view']\n        )\nE       AssertionError: Lists differ: ['a', '/a', 'r2e_tests.test_scripts.test_proutes.view'] != ['a', '/a', 'pyramid.tests.test_scripts.test_proutes.view']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view'\nE       'pyramid.tests.test_scripts.test_proutes.view'\nE       \nE       - ['a', '/a', 'r2e_tests.test_scripts.test_proutes.view']\nE       ?               ^^^\nE       \nE       + ['a', '/a', 'pyramid.tests.test_scripts.test_proutes.view']\nE       ?              ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:155: AssertionError\n______________________ TestPRoutesCommand.test_view_glob _______________________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_view_glob>\n\n    def test_view_glob(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n        def view2(context, request): return 'view2'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        config.add_route('bar', '/b/a')\n        config.add_view(\n            route_name='bar',\n            view=view2,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n        command.options.glob = '*foo*'\n    \n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1',\n            '!POST,*'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', '!POST,*'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', '!POST,*']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', '!POST,*']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', '!POST,*']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:574: AssertionError\n_____________ TestPRoutesCommand.test_view_request_method_not_post _____________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_view_request_method_not_post>\n\n    def test_view_request_method_not_post(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1',\n            '!POST,*'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', '!POST,*'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', '!POST,*']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', '!POST,*']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', '!POST,*']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:533: AssertionError\n_____ TestPViewsCommand.test_views_command_single_view_function_traversal ______\n\nself = <r2e_tests.test_scripts.test_pviews.TestPViewsCommand testMethod=test_views_command_single_view_function_traversal>\n\n    def test_views_command_single_view_function_traversal(self):\n        from pyramid.registry import Registry\n        registry = Registry()\n        command = self._makeOne(registry=registry)\n        L = []\n        command.out = L.append\n        def view(): pass\n        view.__request_attrs__ = {'context': 'context', 'view_name': 'a'}\n        command._find_view = lambda arg1: view\n        command.args = ('/foo/bar/myapp.ini#myapp', '/a')\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(L[1], 'URL = /a')\n        self.assertEqual(L[3], '    context: context')\n        self.assertEqual(L[4], '    view name: a')\n>       self.assertEqual(L[8],\n                         '    pyramid.tests.test_scripts.test_pviews.view')\nE       AssertionError: '    r2e_tests.test_scripts.test_pviews.view' != '    pyramid.tests.test_scripts.test_pviews.view'\nE       -     r2e_tests.test_scripts.test_pviews.view\nE       ?      ^^^\nE       +     pyramid.tests.test_scripts.test_pviews.view\nE       ?     ++ ^^^^^\n\nr2e_tests/test_scripts/test_pviews.py:296: AssertionError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_function_context_and_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_function_requestonly\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_instance_context_and_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_instance_context_and_request_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_instance_requestonly_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_newstyle_class_context_and_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_newstyle_class_context_and_request_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_newstyle_class_requestonly\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_newstyle_class_requestonly_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_oldstyle_class_context_and_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_oldstyle_class_requestonly\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_oldstyle_cls_context_request_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_oldstyle_cls_requestonly_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_attr_wrapped_view_branching_default_phash\nPASSED r2e_tests/test_1.py::TestDeriveView::test_attr_wrapped_view_branching_nondefault_phash\nPASSED r2e_tests/test_1.py::TestDeriveView::test_class_with_attr\nPASSED r2e_tests/test_1.py::TestDeriveView::test_class_without_attr\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_denied\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_denied2\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_overridden\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_permitted\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_permitted_no_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_function_returns_true_Response_no_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_function_returns_true_Response_with_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_prevent_http_cache_in_settings\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_bad_tuple\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_integer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_prevent_auto_set\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_timedelta\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_tuple\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_tuple_seconds_None\nPASSED r2e_tests/test_1.py::TestDeriveView::test_predicate_mismatch_exception_has_text_in_detail\nPASSED r2e_tests/test_1.py::TestDeriveView::test_predicate_mismatch_view_has_name\nPASSED r2e_tests/test_1.py::TestDeriveView::test_predicate_mismatch_view_has_no_name\nPASSED r2e_tests/test_1.py::TestDeriveView::test_requestonly_function\nPASSED r2e_tests/test_1.py::TestDeriveView::test_requestonly_function_with_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_requestonly_function_with_renderer_request_has_view\nPASSED r2e_tests/test_1.py::TestDeriveView::test_requestonly_function_with_renderer_request_override\nPASSED r2e_tests/test_1.py::TestDeriveView::test_secured_view_authn_policy_no_authz_policy\nPASSED r2e_tests/test_1.py::TestDeriveView::test_secured_view_authz_policy_no_authn_policy\nPASSED r2e_tests/test_1.py::TestDeriveView::test_secured_view_raises_forbidden_no_name\nPASSED r2e_tests/test_1.py::TestDeriveView::test_secured_view_raises_forbidden_with_name\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_debug_authorization_authn_policy_no_authz_policy\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_debug_authorization_authz_policy_no_authn_policy\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_debug_authorization_no_authpol\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_debug_authorization_no_permission\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_predicates_all\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_predicates_checker\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_predicates_notall\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_view_mapper_config_specified\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_view_mapper_default_mapper_specified\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_view_mapper_view_specified\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_wrapper_viewname\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_wrapper_viewname_notfound\nPASSED r2e_tests/test_1.py::TestDerivationOrder::test_right_order_implicit\nPASSED r2e_tests/test_1.py::TestDerivationOrder::test_right_order_under_rendered_view\nPASSED r2e_tests/test_1.py::TestDerivationOrder::test_right_order_under_rendered_view_others\nPASSED r2e_tests/test_1.py::TestDerivationOrder::test_right_order_user_sorted\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_enforces_ingress_is_first\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_enforces_mapped_view_is_last\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_enforces_view_is_last\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_reserves_ingress\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_without_name\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_multi_derivers_ordered\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_single_deriver\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_override_deriver\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_override_mapped_view\nPASSED r2e_tests/test_1.py::TestDeriverIntegration::test_unexpected_view_options\nPASSED r2e_tests/test_1.py::TestDeriverIntegration::test_view_options\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_object_event_subscriber\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_resource_url_default_resource_iface_means_Interface\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_resource_url_nodefault_resource_iface\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_response_adapter\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_response_adapter_dottednames\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_response_adapter_self\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_defaults\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_dottednames\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_iface_specified\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_predicate\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_with_default_type_predicates_False\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_with_default_type_predicates_True\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_with_specific_type_and_predicates_False\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_with_specific_type_and_predicates_True\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_traverser_default_iface_means_Interface\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_traverser_introspectables\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_traverser_nondefault_iface\nPASSED r2e_tests/test_config/test_adapters.py::Test_eventonly::test_defaults\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test__override_already_registered\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test__override_not_yet_registered\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_absdirectory\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_absfile\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_file\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_absdirectory\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_absfile\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_directory\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_missing_abspath\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_package\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_package_with_absdirectory\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_samename\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_filename_override_returns_value\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_stream_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_stream_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_stream_override_returns_value\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_string_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_string_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_string_override_returns_value\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_has_resource_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_has_resource_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_has_resource_override_returns_True\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_isdir_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_isdir_override_returns_False\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_isdir_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_listdir_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_listdir_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_listdir_override_returns_values\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_class_conforms_to_IPEP302Loader\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_class_conforms_to_IPackageOverrides\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_package_already_has_loader_of_different_type\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_package_already_has_loader_of_same_type\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_registers_loader_type\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_sets_loader\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_sets_local_state\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_filtered_sources\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_code_pkg_has___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_code_pkg_has_no___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_data_pkg_has___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_data_pkg_has_no___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_filename\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_filename_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_source_pkg_has___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_source_pkg_has_no___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_stream\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_stream_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_string\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_string_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_has_resource\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_has_resource_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_insert_directory\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_insert_emptystring\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_insert_file\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_instance_conforms_to_IPEP302Loader\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_instance_conforms_to_IPackageOverrides\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_is_package_pkg_has___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_is_package_pkg_has_no___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_isdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_isdir_false\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_isdir_true\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_listdir\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_listdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_exists\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_exists_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_exists_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_filename_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_stream\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_stream_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_stream_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_string\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_string_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_string_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_isdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_isdir_false\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_isdir_true\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_listdir\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_listdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_exists\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_exists_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_exists_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_filename\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_filename_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_filename_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_stream\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_stream_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_stream_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_string\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_string_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_string_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_isdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_isdir_false\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_isdir_true\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_listdir\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_listdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestDirectoryOverride::test_it_match\nPASSED r2e_tests/test_config/test_assets.py::TestDirectoryOverride::test_it_no_match\nPASSED r2e_tests/test_config/test_assets.py::TestFileOverride::test_it_match\nPASSED r2e_tests/test_config/test_assets.py::TestFileOverride::test_it_no_match\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_None_callable\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_None_callable_and_no_name\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_None_callable_conflict\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_callable\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_text_type_name\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_unnamed_callable\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_multiple_request_methods_conflict\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_request_factory\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_request_factory_dottedname\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_response_factory\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_response_factory_dottedname\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_root_factory\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_root_factory_as_None\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_root_factory_dottedname\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_session_factory\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_session_factory_dottedname\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_multiple_request_properties\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_multiple_request_properties_conflict\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_request_property_with_callable\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_request_property_with_property\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_request_property_with_unnamed_callable\nPASSED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_missing_dir\nPASSED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_no_specs\nPASSED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_set_locale_negotiator\nPASSED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_set_locale_negotiator_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test___getattr__matches\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test___getattr__matches_no_action_wrap\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test___getattr__missing_when_directives_dont_exist\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test___getattr__missing_when_directives_exist\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_adds__lock\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_adds_clear_view_lookup_cache\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_has_listeners\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_notify\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_queryAdapterOrSelf\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_registerSelfAdapter\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_absolute_asset_spec_already_absolute\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_absolute_asset_spec_notastring\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_absolute_asset_spec_relative\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_autocommit_with_introspectables\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_autocommit_with_introspectables_introspection_off\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_kw_is_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_kw_is_not_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_nonautocommit_with_config_info\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_nonautocommit_with_introspectables\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_nonautocommit_without_config_info\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_nonautocommit_with_introspectables_introspection_off\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_autocommit_no_conflicts\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_begin\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_begin_with_request\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_commit_conflict_resolved_with_include\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_commit_conflict_resolved_with_two_includes_and_local\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_commit_conflict_simple\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_commit_conflict_with_two_includes\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_conflict_set_forbidden_view\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_conflict_set_notfound_view\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_alternate_renderers\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_authentication_policy\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_authorization_policy_only\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_default_permission\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_default_renderers\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_default_view_mapper\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_default_webob_response_adapter_registered\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_exceptionresponse_view_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_exceptionresponse_view_custom\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_httpexception_view_default\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_no_root_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_noreg_custom_settings\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_noreg_debug_logger_non_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_session_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_with_introspection\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_with_package_registry\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_with_root_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_end\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_hook_zca\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_dotted_name\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_missing_source_file\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_module_defaults_to_includeme\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_module_defaults_to_includeme_missing\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_nested_route_prefix\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_python_callable\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_route_prefix\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_introspector_decorator\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_make_wsgi_app\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_maybe_dotted_notstring_success\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_maybe_dotted_string_fail\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_maybe_dotted_string_success\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_dottedname_package\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_with_extra_kw\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_with_ignore\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_with_onerror\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_alternate_renderers\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_authentication_policy\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_authentication_policy_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_authorization_policy_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_authorization_policy_only\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_calls_fix_registry\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_custom_settings\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_debug_logger_name\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_debug_logger_non_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_default_permission\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_dottedname_root_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_explicit_notfound_trumps_iexceptionresponse\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_includes\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_includes_spaces\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_locale_negotiator\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_locale_negotiator_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_no_default_root_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_registers_default_exceptionresponse_views\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_registers_default_view_predicates\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_registers_default_webob_iresponse_adapter\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_request_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_request_factory_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_response_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_tweens\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_unhook_zca\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_with_package\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_with_package_module\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_with_package_package\nPASSED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_directive_persists_across_configurator_creations\nPASSED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_extend_action_method_successful\nPASSED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_extend_same_name_doesnt_conflict\nPASSED r2e_tests/test_config/test_init.py::TestConfigurator__add_predicate::test_factory_as_object\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_simple\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_includepath\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_includepath_and_info\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_info\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_introspectables\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_order\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_dicts\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_error\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_tuples\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_with_introspectable_no_callable\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_with_introspectables\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_it\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_processSpec\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_reentrant_action\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_reentrant_action_error\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_reentrant_action_without_clear\nPASSED r2e_tests/test_config/test_init.py::Test_reentrant_action_functional::test_functional\nPASSED r2e_tests/test_config/test_init.py::Test_resolveConflicts::test_it_conflict\nPASSED r2e_tests/test_config/test_init.py::Test_resolveConflicts::test_it_success_dicts\nPASSED r2e_tests/test_config/test_init.py::Test_resolveConflicts::test_it_success_tuples\nPASSED r2e_tests/test_config/test_init.py::Test_resolveConflicts::test_it_with_actions_grouped_by_order\nPASSED r2e_tests/test_config/test_init.py::TestGlobalRegistriesIntegration::test_global_registries\nPASSED r2e_tests/test_config/test_init.py::TestGlobalRegistriesIntegration::test_global_registries_empty\nPASSED r2e_tests/test_config/test_predicates.py::TestXHRPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestXHRPredicate::test___call___true\nPASSED r2e_tests/test_config/test_predicates.py::TestXHRPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestXHRPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test___call___true_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test___call___true_single\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test_ctor_get_but_no_head\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test___call___true\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test_ctor_compilefail\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___false_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___true_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___true_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___true_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_phash_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_phash_exists_equal_sign\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_phash_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_exists_equal_sign\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_multi_equal_sign\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test___call___matchdict_is_None\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test___call___true_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test___call___true_single\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test___call___true\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test_text_func_has___text__\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test_text_func_repr\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test___call__traverse_has_remainder_already\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test___call__traverse_matches\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test___call__traverse_matches_with_highorder_chars\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_it_call_val_False\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_it_call_val_True\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_it_call_val_str\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___false_withregex\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___true_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___true_withregex\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___true_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_phash_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_phash_withregex\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_phash_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_text_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_text_withregex\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_text_withval\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_False\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_context_has_no_name\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_val_list_True\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_val_str_True\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_val_tuple_True\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_it_call_authentication_policy_doesnt_provide_superset\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_it_call_authentication_policy_provides_superset\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_it_call_authentication_policy_provides_superset_implicit\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_it_call_no_authentication_policy\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_text_noniter\nPASSED r2e_tests/test_config/test_rendering.py::TestRenderingConfiguratorMixin::test_add_default_renderers\nPASSED r2e_tests/test_config/test_rendering.py::TestRenderingConfiguratorMixin::test_add_renderer\nPASSED r2e_tests/test_config/test_rendering.py::TestRenderingConfiguratorMixin::test_add_renderer_dottedname_factory\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_defaults\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_discriminator\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_path_no_pattern\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_pattern_with_path\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_view_with_view_attr\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_view_with_view_context\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_view_with_view_permission\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_view_with_view_renderer\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_accept\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_custom_predicates\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_factory\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_factory_dottedname\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_header\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_path_info\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_path_info_highorder\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_path_info_regex\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_pregenerator\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_request_method\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_request_param\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_route_prefix\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_static\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_xhr\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_get_routes_mapper_already_registered\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_get_routes_mapper_not_yet_registered\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_add_permission\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authentication_policy_no_authz_policy\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authentication_policy_no_authz_policy_autocommit\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authentication_policy_with_authz_policy\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authentication_policy_with_authz_policy_autocommit\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authorization_policy_no_authn_policy\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authorization_policy_no_authn_policy_autocommit\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authorization_policy_with_authn_policy\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authorization_policy_with_authn_policy_autocommit\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_default_permission\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test__set_settings_as_None\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test__set_settings_as_dictwithvalues\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_add_settings_settings_None\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_add_settings_settings_already_registered\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_add_settings_settings_not_yet_registered\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_get_settings_nosettings\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_get_settings_withsettings\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_all\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_authorization\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_notfound\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_routematch\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_templates\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_default_locale_name\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_getattr_fail\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_getattr_raises_attribute_error\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_getattr_success\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_noargs\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_originals_kept\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_prevent_cachebust\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_prevent_http_cache\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_reload_all\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_reload_assets\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_reload_resources\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_reload_templates\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_renderer\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_renderer_explicitrenderer\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_renderer_twice\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_subscriber_defaults\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_subscriber_dottedname\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_subscriber_multiple\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_subscriber_single\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_template\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_resources\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_securitypolicy\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_securitypolicy_forget_result\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_securitypolicy_remember_result\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_dottedname\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_instance\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_name_ingress\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_name_main\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_over_ingress\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_over_ingress_iterable\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_under_main\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_under_main_iterable\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_unsuitable\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_conflict\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_names_distinct\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_names_with_over_nonstringoriter\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_names_with_under_nonstringoriter\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_names_with_underover\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test___call___explicit\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test___call___implicit\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_add_explicit\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_add_implicit\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_1\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_2\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_3\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_4\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_5\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_conflict_direct\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_conflict_indirect\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_over_and_under_partials\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_over_partial\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_over_partial_with_fallback\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_under_partial\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_under_partial_with_fallback\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_with_missing_fallbacks\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_with_multiple_matching_fallbacks\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_with_partial_fallbacks\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_custom_predicates_can_affect_traversal\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_different_custom_predicates_with_same_hash\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_match_param_from_dict\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_match_param_from_dict_fails\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_match_param_from_string\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_match_param_from_string_fails\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_notted\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_ordering_importance_and_number\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_ordering_importance_of_predicates\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_ordering_number_of_predicates\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_ordering_xhr_and_request_method_trump_only_containment\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_predicate_text_is_correct\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_request_method_ordering_hashes_same\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_request_method_sequence\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_traverse_has_remainder_already\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_traverse_matches\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_traverse_matches_with_highorder_chars\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_unknown_predicate\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_annotations\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_defaultargs_firstname_not_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_defaultargs_firstname_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_noargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_onearg_named_somethingelse\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_toomanyargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_with_attr_false\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_with_attr_true\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_defaultargs_firstname_not_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_defaultargs_firstname_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_defaultargs_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_defaultargs_onearg_named_somethingelse\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_nocall\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_toomanyargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_method_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_defaultargs_firstname_not_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_defaultargs_firstname_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_firstname_request_with_secondname\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_noargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_onearg_named_somethingelse\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_defaultargs_firstname_not_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_defaultargs_firstname_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_noargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_onearg_named_somethingelse\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_toomanyargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_no_init\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_requestonly_newstyle_class_init_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_requestonly_newstyle_class_init_toomanyargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_requestonly_newstyle_class_no_init\nPASSED r2e_tests/test_config/test_util.py::TestNotted::test_it_with_phash_val\nPASSED r2e_tests/test_config/test_util.py::TestNotted::test_it_without_phash_val\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_allows_other_predicates\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_context\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_for_\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_http_cache\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_no_view_argument\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_with_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_with_view_defaults\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_allows_other_predicates\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_append_slash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_append_slash_custom_response\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_context\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_for_\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_http_cache\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_no_view_argument\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_with_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_with_view_defaults\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_static_view_absolute\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_static_view_here_no_utility_registered\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_static_view_package_relative\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_instance\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_instance_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_instancemethod\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_instancemethod_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_oldstyle_class\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_oldstyle_class_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_class_method_no_attr\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_context_as_class\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_context_as_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_context_as_iface\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_context_trumps_for\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_custom_more_preds_first_bests_fewer_preds_last\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_custom_predicate_bests_standard_predicate\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_default_phash_overrides_default_phash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_default_phash_overrides_no_phash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_default_phash_overrides_default_phash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_default_phash_overrides_no_phash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_multiview_replaces_existing_securedview\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_multiview_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_multiview_replaces_multiview\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_mulview_replaces_existing_view_with___accept__\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_same_phash_overrides_existing_single_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_with_accept_multiview_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exception_register_secured_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_for__as_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_for_as_class\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_for_as_iface\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_mixed_case_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview___discriminator__\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_call_ordering\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_context_superclass_then_subclass\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_exception_superclass_then_subclass\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_replaces_existing_securedview\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_replaces_existing_view_with___accept__\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_replaces_multiview\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_register_secured_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_same_phash_overrides_existing_single_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_same_predicates\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_view_callable_None_no_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_view_callable_None_with_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_view_callable_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_accept_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_accept_multiview_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_accept_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_containment_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_containment_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_containment_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_custom_predicates_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_custom_predicates_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_decorator\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_decorator_tuple\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_default_permission_no_explicit_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_default_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_function_callable\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_function_callable_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_badregex\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_noval_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_noval_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_val_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_val_missing\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_val_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_http_cache\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_mapper\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_name_unicode\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_no_default_permission_no_explicit_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_nonexistant_route_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_path_info_badregex\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_path_info_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_path_info_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_get_implies_head\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_sequence_conflict\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_sequence_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_sequence_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_param_noval_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_param_noval_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_param_val_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_param_val_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_type\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_type_and_route_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_type_as_iface\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_type_as_noniface\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_route_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_route_name_exception\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_tmpl_renderer_factory_introspector_missing\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_tmpl_renderer_factory_no_renderer_factory\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_tmpl_renderer_factory_with_renderer_factory\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_config_and_view_defaults_conflicts\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_config_and_view_defaults_doesnt_conflict\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_defaults\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_defaults_viewname_is_dottedname_kwarg\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_defaults_viewname_is_dottedname_nonkwarg\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_xhr_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_xhr_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_wrapped_view_is_decorated\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_views_with_accept_multiview_replaces_existing\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_derive_view_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_derive_view_function\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_derive_view_with_default_renderer_no_explicit_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_derive_view_with_default_renderer_with_explicit_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_set_view_mapper\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_set_view_mapper_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_view_with_most_specific_predicate\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_view_with_most_specific_predicate_with_mismatch\nPASSED r2e_tests/test_config/test_views.py::Test_requestonly::test_defaults\nPASSED r2e_tests/test_config/test_views.py::Test_requestonly::test_otherattr\nPASSED r2e_tests/test_config/test_views.py::Test_isexception::test_is_IException\nPASSED r2e_tests/test_config/test_views.py::Test_isexception::test_is_IException_subinterface\nPASSED r2e_tests/test_config/test_views.py::Test_isexception::test_is_exception_class\nPASSED r2e_tests/test_config/test_views.py::Test_isexception::test_is_exception_instance\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call__\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call__intermediate_not_found\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call__raise_not_found_isnt_interpreted_as_pred_mismatch\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call_permissive_has_call_permissive\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call_permissive_has_no_call_permissive\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test__call__not_found\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test__call__with_accept_match\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test__call__with_accept_miss\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test__call_permissive__not_found\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_add\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_add_with_phash\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_add_with_phash_override_accept\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_add_with_phash_override_accept2\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_class_implements_ISecuredView\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_get_views\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_get_views_best_match_returns_None\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_get_views_no_self_accepts\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_get_views_request_has_no_accept\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_instance_implements_ISecuredView\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_match_not_found\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_match_predicate_fails\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_match_predicate_succeeds\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_multiple_with_functions_as_views\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_permitted\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_permitted_no_match_with__permitted__\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_permitted_no_views\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test__view_as_function_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_function_context_and_request\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_function_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_function_requestonly_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_instance_context_and_request\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_instance_context_and_request_and_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_instance_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_instance_requestonly_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_newstyle_class_context_and_request\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_newstyle_class_context_and_request_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_newstyle_class_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_newstyle_class_requestonly_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_oldstyle_class_context_and_request\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_oldstyle_class_context_and_request_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_oldstyle_class_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_oldstyle_class_requestonly_with_attr\nPASSED r2e_tests/test_config/test_views.py::Test_preserve_view_attrs::test_it_different\nPASSED r2e_tests/test_config/test_views.py::Test_preserve_view_attrs::test_it_different_with_existing_original_view\nPASSED r2e_tests/test_config/test_views.py::Test_preserve_view_attrs::test_it_same\nPASSED r2e_tests/test_config/test_views.py::Test_preserve_view_attrs::test_it_view_is_None\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_already_exists\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebust_prevented\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster_abspath\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster_for_more_specific_path\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster_overwrite\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster_overwrite_explicit\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_package_root\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_url_noendslash\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_url_noscheme\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_url_withendslash\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_context\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_for_\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_permission\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_renderer\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_route_prefix\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_missing\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_quoting\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_registration_miss\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_route_url\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_slash_in_name1\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_slash_in_name2\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_cachebust\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_cachebust_abspath\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_cachebust_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_quoted_remote\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_unquoted_local\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_with_custom_anchor\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_with_custom_query\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_verifyClass\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_verifyObject\nPASSED r2e_tests/test_config/test_views.py::Test_view_description::test_with_text\nPASSED r2e_tests/test_scripts/test_common.py::Test_logging_file_config::test_it\nPASSED r2e_tests/test_scripts/test_common.py::TestParseVars::test_parse_vars_bad\nPASSED r2e_tests/test_scripts/test_common.py::TestParseVars::test_parse_vars_good\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_confirm_override_conflicting_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_force_override_conflicting_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_force_override_site_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_known_scaffold_absolute_path\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_known_scaffold_multiple_rendered\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_known_scaffold_single_rendered\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_known_scaffold_with_path_as_project_target_rendered\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_no_project_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_run_no_scaffold_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_run_no_scaffold_no_args\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_run_show_scaffolds_exist\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_run_show_scaffolds_none_exist\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_dev_pyramid_long_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_dev_pyramid_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_hyphen_in_project_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_prod_pyramid_long_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_prod_pyramid_unparsable_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_prod_pyramid_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_unknown_scaffold_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_pdistreport.py::TestPDistReportCommand::test_no_dists\nPASSED r2e_tests/test_scripts/test_pdistreport.py::TestPDistReportCommand::test_with_dists\nPASSED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_has_bad_config_header\nPASSED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_configures_logging\nPASSED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_not_enough_args\nPASSED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_response_has_no_charset\nPASSED r2e_tests/test_scripts/test_prequest.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test__get_mapper\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_bad_args\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_bad_format\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_good_args\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_good_format\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_no_mapper\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_no_routes\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_as_wsgiapp\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_no_view\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_with_no_slash_prefix\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_multiview_registered\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_no_route_registered\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_no_views_registered\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_one_view_registered_with_factory\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_static_routes_included_in_list\nPASSED r2e_tests/test_scripts/test_proutes.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_get_options_no_command\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_get_options_with_command\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_parse_vars_bad\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_parse_vars_good\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_record_pid_not_verbose\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_record_pid_verbose\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_current_pid_is_not_pid_in_file\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_current_pid_is_not_written_pid\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_file_not_verbose\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_file_stale_pid_write_exception\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_file_unlink_exception\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_file_verbose\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_no_pid_file\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_not_a_number\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_run_no_args\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_run_stop_daemon_bad_pid_file\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_run_stop_daemon_invalid_pid_in_file\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_run_stop_daemon_no_such_pid_file\nPASSED r2e_tests/test_scripts/test_pserve.py::Test_read_pidfile::test_read_pidfile\nPASSED r2e_tests/test_scripts/test_pserve.py::Test_read_pidfile::test_read_pidfile_no_pid_file\nPASSED r2e_tests/test_scripts/test_pserve.py::Test_read_pidfile::test_read_pidfile_not_a_number\nPASSED r2e_tests/test_scripts/test_pserve.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_pserve.py::TestLazyWriter::test_flush\nPASSED r2e_tests/test_scripts/test_pserve.py::TestLazyWriter::test_open\nPASSED r2e_tests/test_scripts/test_pserve.py::TestLazyWriter::test_write\nPASSED r2e_tests/test_scripts/test_pserve.py::TestLazyWriter::test_writeline\nPASSED r2e_tests/test_scripts/test_pserve.py::Test__methodwrapper::test___call__fail\nPASSED r2e_tests/test_scripts/test_pserve.py::Test__methodwrapper::test___call__succeed\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_custom_section_override\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_default_shell_option\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_errors_with_unknown_shell\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_check_variable_override_order\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_custom_items\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_default_shell\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_ipython\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_pythonstartup\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_setup_from_options\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_setup\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_list_shells\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_shell_entry_points\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_shell_ordering\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_shell_override\nPASSED r2e_tests/test_scripts/test_pshell.py::Test_python_shell_runner::test_it\nPASSED r2e_tests/test_scripts/test_pshell.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_ptweens.py::TestPTweensCommand::test__get_tweens\nPASSED r2e_tests/test_scripts/test_ptweens.py::TestPTweensCommand::test_command_implicit_and_explicit_tweens\nPASSED r2e_tests/test_scripts/test_ptweens.py::TestPTweensCommand::test_command_implicit_tweens_only\nPASSED r2e_tests/test_scripts/test_ptweens.py::TestPTweensCommand::test_command_no_tweens\nPASSED r2e_tests/test_scripts/test_ptweens.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_multi_routes_all_match\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_multi_routes_none_match\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_multi_routes_some_match\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_no_match\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_no_match_multiview_registered\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_route_multiview\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_route_multiview_no_view_registered\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_route_no_multiview\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_traversal\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_traversal_multiview\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_multi_view_nested\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_multiview\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_multiview_with_permission\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_multiview_with_predicates\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_not_found\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_not_found_url_starts_without_slash\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_route\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_route_with_route_predicates\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_traversal\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_traversal_with_permission\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_traversal_with_predicates\nPASSED r2e_tests/test_scripts/test_pviews.py::Test_main::test_it\nFAILED r2e_tests/test_1.py::TestDeriveView::test_as_instance_requestonly - As...\nFAILED r2e_tests/test_1.py::TestDeriveView::test_function_returns_non_adaptable\nFAILED r2e_tests/test_1.py::TestDeriveView::test_function_returns_non_adaptable_dict\nFAILED r2e_tests/test_1.py::TestDeriveView::test_instance_returns_non_adaptable\nFAILED r2e_tests/test_1.py::TestDeriveView::test_requestonly_default_method_returns_non_adaptable\nFAILED r2e_tests/test_1.py::TestDeriveView::test_requestonly_nondefault_method_returns_non_adaptable\nFAILED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_resource_url_adapter_dotted_names\nFAILED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_resource_url_adapter_introspectables\nFAILED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_traverser_dotted_names\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_directory\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_package\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_file\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_package_with_directory\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_package_with_package\nFAILED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_filename_no_overrides\nFAILED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_filename_override_returns_None\nFAILED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_filename\nFAILED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_filename_with_prefix\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_abspath\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_asset_spec\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_asset_spec_existing_translation_dirs\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_multiple_specs\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_multiple_specs_multiple_calls\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_no_registry\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_noreg_debug_logger_None_default\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_constant_root_package\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_conflict\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_debug_logger_None_default\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_add_directive_with_custom_callable\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_add_directive_with_partial\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_extend_with_dotted_name\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_extend_with_python_callable\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator__add_predicate::test_factory_as_dotted_name\nFAILED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_static_view_package_here_relative\nFAILED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_template_renderer\nFAILED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_template_renderer_no_callable\nFAILED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_cachebust_with_overrides\nFAILED r2e_tests/test_config/test_views.py::Test_view_description::test_without_text\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_display_headers\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_has_content_type_header_var\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_has_good_header_var\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_has_multiple_header_vars\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_get\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_options\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_patch\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_post\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_propfind\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_put\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_path_doesnt_start_with_slash\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_two_args\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_w_basic_auth\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_with_query_string\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_config_format_ini_commas\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_config_format_ini_newlines\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_config_format_ini_spaces\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_one_route_all_methods_view_only_post\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_one_route_only_post_view_all_methods\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_one_route_only_post_view_post_and_get\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_one_route_with_long_name_one_view_registered\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_is_get_view_request_method_not_post\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_request_method_mismatch\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_static_views\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_one_view_registered\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_view_glob\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_view_request_method_not_post\nFAILED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_function_traversal\n======================== 66 failed, 897 passed in 5.50s ========================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.8.20, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f\ncollected 963 items\n\nr2e_tests/test_1.py ....F..................FF.........F...F....F........ [  5%]\n............FFF.....F..                                                  [  7%]\nr2e_tests/test_config/test_adapters.py .FF..............F...             [  9%]\nr2e_tests/test_config/test_assets.py ....F.F...F...FF.FF................ [ 13%]\n.....................................F.F................................ [ 21%]\n                                                                         [ 21%]\nr2e_tests/test_config/test_factories.py .....................            [ 23%]\nr2e_tests/test_config/test_i18n.py FFF.FF...                             [ 24%]\nr2e_tests/test_config/test_init.py ..................................... [ 28%]\n...F..F.......F.............F...........F.....................FF...FFF.. [ 35%]\n......................                                                   [ 37%]\nr2e_tests/test_config/test_predicates.py ............................... [ 41%]\n...........................................                              [ 45%]\nr2e_tests/test_config/test_rendering.py ...                              [ 45%]\nr2e_tests/test_config/test_routes.py ........................            [ 48%]\nr2e_tests/test_config/test_security.py ..........                        [ 49%]\nr2e_tests/test_config/test_settings.py ........................          [ 51%]\nr2e_tests/test_config/test_testing.py ............                       [ 53%]\nr2e_tests/test_config/test_tweens.py .................................   [ 56%]\nr2e_tests/test_config/test_util.py ..................................... [ 60%]\n..............                                                           [ 61%]\nr2e_tests/test_config/test_views.py ........................F........... [ 65%]\n........................................................................ [ 73%]\n......FF................................................................ [ 80%]\n..................................F.......F                              [ 84%]\nr2e_tests/test_scripts/test_common.py ...                                [ 85%]\nr2e_tests/test_scripts/test_pcreate.py ....................              [ 87%]\nr2e_tests/test_scripts/test_pdistreport.py ..                            [ 87%]\nr2e_tests/test_scripts/test_prequest.py F.FFF.FFFFFF.F.FFF.              [ 89%]\nr2e_tests/test_scripts/test_proutes.py ...FFF....FFFF.F.FF....F..FF.     [ 92%]\nr2e_tests/test_scripts/test_pserve.py ............................       [ 95%]\nr2e_tests/test_scripts/test_pshell.py ................                   [ 97%]\nr2e_tests/test_scripts/test_ptweens.py .....                             [ 97%]\nr2e_tests/test_scripts/test_pviews.py ................F......            [100%]\n\n=================================== FAILURES ===================================\n_________________ TestDeriveView.test_as_instance_requestonly __________________\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_as_instance_requestonly>\n\n    def test_as_instance_requestonly(self):\n        response = DummyResponse()\n        class View:\n            def __call__(self, request):\n                return response\n        view = View()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        self.assertEqual(view.__module__, result.__module__)\n        self.assertEqual(view.__doc__, result.__doc__)\n>       self.assertTrue('test_viewderivers' in result.__name__)\nE       AssertionError: False is not true\n\nr2e_tests/test_1.py:361: AssertionError\n______________ TestDeriveView.test_function_returns_non_adaptable ______________\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_function_returns_non_adaptable>\n\n    def test_function_returns_non_adaptable(self):\n        def view(request):\n            return None\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n>           result(None, None)\n\nr2e_tests/test_1.py:44: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None, request = None\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable function r2e_tests.test_1.view into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_function_returns_non_adaptable>\n\n    def test_function_returns_non_adaptable(self):\n        def view(request):\n            return None\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n>           self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable function '\n                'pyramid.tests.test_viewderivers.view into a response '\n                'object. The value returned was None. You may have forgotten '\n                'to return a value from the view callable.'\n                )\nE           AssertionError: 'Coul[52 chars]tion r2e_tests.test_1.view into a response obj[94 chars]ble.' != 'Coul[52 chars]tion pyramid.tests.test_viewderivers.view into[109 chars]ble.'\nE           - Could not convert return value of the view callable function r2e_tests.test_1.view into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\nE           ?                                                              ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^\nE           + Could not convert return value of the view callable function pyramid.tests.test_viewderivers.view into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\nE           ?                                                              ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^\n\nr2e_tests/test_1.py:46: AssertionError\n___________ TestDeriveView.test_function_returns_non_adaptable_dict ____________\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_function_returns_non_adaptable_dict>\n\n    def test_function_returns_non_adaptable_dict(self):\n        def view(request):\n            return {'a':1}\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n>           result(None, None)\n\nr2e_tests/test_1.py:62: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None, request = None\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable function r2e_tests.test_1.view into a response object. The value returned was {'a': 1}. You may have forgotten to define a renderer in the view configuration.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_function_returns_non_adaptable_dict>\n\n    def test_function_returns_non_adaptable_dict(self):\n        def view(request):\n            return {'a':1}\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n>           self.assertEqual(\n                e.args[0],\n                \"Could not convert return value of the view callable function \"\n                \"pyramid.tests.test_viewderivers.view into a response \"\n                \"object. The value returned was {'a': 1}. You may have \"\n                \"forgotten to define a renderer in the view configuration.\"\n                )\nE           AssertionError: \"Coul[52 chars]tion r2e_tests.test_1.view into a response obj[104 chars]ion.\" != \"Coul[52 chars]tion pyramid.tests.test_viewderivers.view into[119 chars]ion.\"\nE           Diff is 641 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_1.py:64: AssertionError\n______________ TestDeriveView.test_instance_returns_non_adaptable ______________\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_instance_returns_non_adaptable>\n\n    def test_instance_returns_non_adaptable(self):\n        class AView(object):\n            def __call__(self, request):\n                return None\n        view = AView()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n>           result(None, None)\n\nr2e_tests/test_1.py:82: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None, request = None\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable object <r2e_tests.test_1.TestDeriveView.test_instance_returns_non_adaptable.<locals>.AView object at 0x758102420dc0> into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_instance_returns_non_adaptable>\n\n    def test_instance_returns_non_adaptable(self):\n        class AView(object):\n            def __call__(self, request):\n                return None\n        view = AView()\n        result = self.config.derive_view(view)\n        self.assertFalse(result is view)\n        try:\n            result(None, None)\n        except ValueError as e:\n            msg = e.args[0]\n>           self.assertTrue(msg.startswith(\n                'Could not convert return value of the view callable object '\n                '<pyramid.tests.test_viewderivers.'))\nE           AssertionError: False is not true\n\nr2e_tests/test_1.py:85: AssertionError\n_____ TestDeriveView.test_requestonly_default_method_returns_non_adaptable _____\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_requestonly_default_method_returns_non_adaptable>\n\n    def test_requestonly_default_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return None\n        result = self.config.derive_view(AView)\n        self.assertFalse(result is AView)\n        try:\n>           result(None, request)\n\nr2e_tests/test_1.py:125: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None\nrequest = <r2e_tests.test_1.DummyRequest object at 0x7581021fa0d0>\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable method __call__ of class r2e_tests.test_1.AView into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_requestonly_default_method_returns_non_adaptable>\n\n    def test_requestonly_default_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def __call__(self):\n                return None\n        result = self.config.derive_view(AView)\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n>           self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method __call__ of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\nE           AssertionError: 'Coul[68 chars]lass r2e_tests.test_1.AView into a response ob[95 chars]ble.' != 'Coul[68 chars]lass pyramid.tests.test_viewderivers.AView int[110 chars]ble.'\nE           Diff is 663 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_1.py:127: AssertionError\n___ TestDeriveView.test_requestonly_nondefault_method_returns_non_adaptable ____\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_requestonly_nondefault_method_returns_non_adaptable>\n\n    def test_requestonly_nondefault_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def theviewmethod(self):\n                return None\n        result = self.config.derive_view(AView, attr='theviewmethod')\n        self.assertFalse(result is AView)\n        try:\n>           result(None, request)\n\nr2e_tests/test_1.py:148: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\ncontext = None\nrequest = <r2e_tests.test_1.DummyRequest object at 0x7581023fd9a0>\n\n    def viewresult_to_response(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # common case\n            response = result\n        else:\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                if result is None:\n                    append = (' You may have forgotten to return a value '\n                              'from the view callable.')\n                elif isinstance(result, dict):\n                    append = (' You may have forgotten to define a '\n                              'renderer in the view configuration.')\n                else:\n                    append = ''\n    \n                msg = ('Could not convert return value of the view '\n                       'callable %s into a response object. '\n                       'The value returned was %r.' + append)\n    \n>               raise ValueError(msg % (view_description(view), result))\nE               ValueError: Could not convert return value of the view callable method theviewmethod of class r2e_tests.test_1.AView into a response object. The value returned was None. You may have forgotten to return a value from the view callable.\n\npyramid/viewderivers.py:410: ValueError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestDeriveView testMethod=test_requestonly_nondefault_method_returns_non_adaptable>\n\n    def test_requestonly_nondefault_method_returns_non_adaptable(self):\n        request = DummyRequest()\n        class AView(object):\n            def __init__(self, request):\n                pass\n            def theviewmethod(self):\n                return None\n        result = self.config.derive_view(AView, attr='theviewmethod')\n        self.assertFalse(result is AView)\n        try:\n            result(None, request)\n        except ValueError as e:\n>           self.assertEqual(\n                e.args[0],\n                'Could not convert return value of the view callable '\n                'method theviewmethod of '\n                'class pyramid.tests.test_viewderivers.AView into a '\n                'response object. The value returned was None. You may have '\n                'forgotten to return a value from the view callable.'\n                )\nE           AssertionError: 'Coul[73 chars]lass r2e_tests.test_1.AView into a response ob[95 chars]ble.' != 'Coul[73 chars]lass pyramid.tests.test_viewderivers.AView int[110 chars]ble.'\nE           Diff is 683 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_1.py:150: AssertionError\n__________ TestAddDeriver.test_add_deriver_enforces_ingress_is_first ___________\n\nself = <r2e_tests.test_1.TestAddDeriver testMethod=test_add_deriver_enforces_ingress_is_first>\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n>           self.config.add_view_deriver(deriv1, over=INGRESS)\n\nr2e_tests/test_1.py:1304: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \npyramid/util.py:573: in wrapper\n    result = wrapped(self, *arg, **kw)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <pyramid.config.Configurator object at 0x7581027be6d0>\nderiver = <function TestAddDeriver.test_add_deriver_enforces_ingress_is_first.<locals>.deriv1 at 0x75810244aee0>\nname = 'deriv1', under = None, over = ('INGRESS',)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n    \n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n    \n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n    \n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n    \n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n    \n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n    \n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n    \n        See :ref:`view_derivers` for more information.\n    \n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n    \n        if name is None:\n            name = deriver.__name__\n    \n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n    \n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n    \n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n    \n        if under is None:\n>           raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\nE           pyramid.exceptions.ConfigurationError: must specify an \"under\" constraint for the deriv1 view deriver\n\npyramid/config/views.py:1146: ConfigurationError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestAddDeriver testMethod=test_add_deriver_enforces_ingress_is_first>\n\n    def test_add_deriver_enforces_ingress_is_first(self):\n        from pyramid.exceptions import ConfigurationError\n        from pyramid.viewderivers import INGRESS\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, over=INGRESS)\n        except ConfigurationError as ex:\n>           self.assertTrue('cannot be over INGRESS' in ex.args[0])\nE           AssertionError: False is not true\n\nr2e_tests/test_1.py:1306: AssertionError\n_________ TestAddDeriver.test_add_deriver_enforces_mapped_view_is_last _________\n\nself = <r2e_tests.test_1.TestAddDeriver testMethod=test_add_deriver_enforces_mapped_view_is_last>\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n>           self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n\nr2e_tests/test_1.py:1325: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \npyramid/util.py:573: in wrapper\n    result = wrapped(self, *arg, **kw)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <pyramid.config.Configurator object at 0x75810241ad30>\nderiver = <function TestAddDeriver.test_add_deriver_enforces_mapped_view_is_last.<locals>.deriv1 at 0x75810226cee0>\nname = 'deriv1', under = 'mapped_view', over = None\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n    \n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n    \n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n    \n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n    \n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n    \n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n    \n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n    \n        See :ref:`view_derivers` for more information.\n    \n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n    \n        if name is None:\n            name = deriver.__name__\n    \n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n    \n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n    \n        if over is None and name != MAPPED_VIEW:\n>           raise ConfigurationError('must specify an \"over\" constraint for '\nE           pyramid.exceptions.ConfigurationError: must specify an \"over\" constraint for the deriv1 view deriver\n\npyramid/config/views.py:1140: ConfigurationError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_1.TestAddDeriver testMethod=test_add_deriver_enforces_mapped_view_is_last>\n\n    def test_add_deriver_enforces_mapped_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n        def deriv1(view, info): pass\n        try:\n            self.config.add_view_deriver(deriv1, 'deriv1', under='mapped_view')\n        except ConfigurationError as ex:\n>           self.assertTrue('cannot be under \"mapped_view\"' in ex.args[0])\nE           AssertionError: False is not true\n\nr2e_tests/test_1.py:1327: AssertionError\n____________ TestAddDeriver.test_add_deriver_enforces_view_is_last _____________\n\nself = <r2e_tests.test_1.TestAddDeriver testMethod=test_add_deriver_enforces_view_is_last>\n\n    def test_add_deriver_enforces_view_is_last(self):\n        from pyramid.exceptions import ConfigurationError\n>       from pyramid.viewderivers import VIEW\nE       ImportError: cannot import name 'VIEW' from 'pyramid.viewderivers' (/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/viewderivers.py)\n\nr2e_tests/test_1.py:1312: ImportError\n___________________ TestAddDeriver.test_override_mapped_view ___________________\n\nself = <r2e_tests.test_1.TestAddDeriver testMethod=test_override_mapped_view>\n\n    def test_override_mapped_view(self):\n>       from pyramid.viewderivers import VIEW\nE       ImportError: cannot import name 'VIEW' from 'pyramid.viewderivers' (/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/viewderivers.py)\n\nr2e_tests/test_1.py:1243: ImportError\n__ AdaptersConfiguratorMixinTests.test_add_resource_url_adapter_dotted_names ___\n\nself = <r2e_tests.test_config.test_adapters.AdaptersConfiguratorMixinTests testMethod=test_add_resource_url_adapter_dotted_names>\n\n    def test_add_resource_url_adapter_dotted_names(self):\n        from pyramid.interfaces import IResourceURL\n        config = self._makeOne(autocommit=True)\n        config.add_resource_url_adapter(\n            'pyramid.tests.test_config.test_adapters.DummyResourceURL',\n            'pyramid.tests.test_config.test_adapters.DummyIface',\n            )\n        iface = DummyIface()\n>       adapter = config.registry.getMultiAdapter((iface, iface),\n                                                    IResourceURL)\n\nr2e_tests/test_config/test_adapters.py:280: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Registry r2e_tests.test_config>\nobjects = (<r2e_tests.test_config.test_adapters.DummyIface object at 0x758102391dc0>, <r2e_tests.test_config.test_adapters.DummyIface object at 0x758102391dc0>)\ninterface = <InterfaceClass pyramid.interfaces.IResourceURL>, name = ''\n\n    def getMultiAdapter(self, objects, interface, name=''):\n        adapter = self.adapters.queryMultiAdapter(objects, interface, name)\n        if adapter is None:\n>           raise ComponentLookupError(objects, interface, name)\nE           zope.interface.interfaces.ComponentLookupError: ((<r2e_tests.test_config.test_adapters.DummyIface object at 0x758102391dc0>, <r2e_tests.test_config.test_adapters.DummyIface object at 0x758102391dc0>), <InterfaceClass pyramid.interfaces.IResourceURL>, '')\n\n.venv/lib/python3.8/site-packages/zope/interface/registry.py:379: ComponentLookupError\n_ AdaptersConfiguratorMixinTests.test_add_resource_url_adapter_introspectables _\n\nself = <r2e_tests.test_config.test_adapters.AdaptersConfiguratorMixinTests testMethod=test_add_resource_url_adapter_introspectables>\n\n    def test_add_resource_url_adapter_introspectables(self):\n        config = self._makeOne()\n        config.add_resource_url_adapter(DummyResourceURL, DummyIface)\n        actions = config.action_state.actions\n        self.assertEqual(len(actions), 1)\n        intrs  = actions[0]['introspectables']\n        self.assertEqual(len(intrs), 1)\n        intr = intrs[0]\n        self.assertEqual(intr.type_name, 'resource url adapter')\n        self.assertEqual(intr.discriminator,\n                         ('resource url adapter', DummyIface))\n        self.assertEqual(intr.category_name, 'resource url adapters')\n>       self.assertEqual(\n            intr.title,\n            \"resource url adapter for resource iface \"\n            \"<class 'pyramid.tests.test_config.test_adapters.DummyIface'>\"\n            )\nE       AssertionError: \"reso[34 chars]e <class 'r2e_tests.test_config.test_adapters.DummyIface'>\" != \"reso[34 chars]e <class 'pyramid.tests.test_config.test_adapters.DummyIface'>\"\nE       - resource url adapter for resource iface <class 'r2e_tests.test_config.test_adapters.DummyIface'>\nE       ?                                                  ^^^\nE       + resource url adapter for resource iface <class 'pyramid.tests.test_config.test_adapters.DummyIface'>\nE       ?                                                 ++ ^^^^^\n\nr2e_tests/test_config/test_adapters.py:326: AssertionError\n________ AdaptersConfiguratorMixinTests.test_add_traverser_dotted_names ________\n\nself = <r2e_tests.test_config.test_adapters.AdaptersConfiguratorMixinTests testMethod=test_add_traverser_dotted_names>\n\n    def test_add_traverser_dotted_names(self):\n        from pyramid.interfaces import ITraverser\n        config = self._makeOne(autocommit=True)\n        config.add_traverser(\n            'pyramid.tests.test_config.test_adapters.DummyTraverser',\n            'pyramid.tests.test_config.test_adapters.DummyIface')\n        iface = DummyIface()\n>       traverser = config.registry.getAdapter(iface, ITraverser)\n\nr2e_tests/test_config/test_adapters.py:237: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Registry r2e_tests.test_config>\nobject = <r2e_tests.test_config.test_adapters.DummyIface object at 0x75810215f130>\ninterface = <InterfaceClass pyramid.interfaces.ITraverser>, name = ''\n\n    def getAdapter(self, object, interface, name=''):\n        adapter = self.adapters.queryAdapter(object, interface, name)\n        if adapter is None:\n>           raise ComponentLookupError(object, interface, name)\nE           zope.interface.interfaces.ComponentLookupError: (<r2e_tests.test_config.test_adapters.DummyIface object at 0x75810215f130>, <InterfaceClass pyramid.interfaces.ITraverser>, '')\n\n.venv/lib/python3.8/site-packages/zope/interface/registry.py:368: ComponentLookupError\n___ TestAssetsConfiguratorMixin.test_override_asset_directory_with_directory ___\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_directory_with_directory>\n\n    def test_override_asset_directory_with_directory(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset:templates/',\n            'pyramid.tests.test_config.pkgs.asset.subpackage:templates/',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, 'templates/')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, 'templates/')\n    \n        resource_name = 'bar.pt'\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:106: AssertionError\n____ TestAssetsConfiguratorMixin.test_override_asset_directory_with_package ____\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_directory_with_package>\n\n    def test_override_asset_directory_with_package(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset:templates/',\n            'pyramid.tests.test_config.pkgs.asset.subpackage',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, 'templates/')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, '')\n    \n        resource_name = 'templates/bar.pt'\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:129: AssertionError\n________ TestAssetsConfiguratorMixin.test_override_asset_file_with_file ________\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_file_with_file>\n\n    def test_override_asset_file_with_file(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset:templates/foo.pt',\n            'pyramid.tests.test_config.pkgs.asset.subpackage:templates/bar.pt',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, 'templates/foo.pt')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, 'templates/bar.pt')\n    \n        resource_name = ''\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:60: AssertionError\n____ TestAssetsConfiguratorMixin.test_override_asset_package_with_directory ____\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_package_with_directory>\n\n    def test_override_asset_package_with_directory(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset',\n            'pyramid.tests.test_config.pkgs.asset.subpackage:templates/',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, '')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, 'templates/')\n    \n        resource_name = 'bar.pt'\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:152: AssertionError\n_____ TestAssetsConfiguratorMixin.test_override_asset_package_with_package _____\n\nself = <r2e_tests.test_config.test_assets.TestAssetsConfiguratorMixin testMethod=test_override_asset_package_with_package>\n\n    def test_override_asset_package_with_package(self):\n        from pyramid.config.assets import PackageAssetSource\n        config = self._makeOne(autocommit=True)\n        override = DummyUnderOverride()\n        config.override_asset(\n            'pyramid.tests.test_config.pkgs.asset',\n            'pyramid.tests.test_config.pkgs.asset.subpackage',\n            _override=override)\n        from pyramid.tests.test_config.pkgs import asset\n        from pyramid.tests.test_config.pkgs.asset import subpackage\n        self.assertEqual(override.package, asset)\n        self.assertEqual(override.path, '')\n        source = override.source\n        self.assertTrue(isinstance(source, PackageAssetSource))\n        self.assertEqual(source.package, subpackage)\n        self.assertEqual(source.prefix, '')\n    \n        resource_name = 'templates/bar.pt'\n        expected = os.path.join(here, 'pkgs', 'asset',\n                                'subpackage', 'templates', 'bar.pt')\n>       self.assertEqual(override.source.get_filename(resource_name),\n                         expected)\nE       AssertionError: '/hom[90 chars]d31f/pyramid/tests/test_config/pkgs/asset/subp[19 chars]r.pt' != '/hom[90 chars]d31f/r2e_tests/test_config/pkgs/asset/subpacka[15 chars]r.pt'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/pkgs/asset/subpackage/templates/bar.pt\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:83: AssertionError\n_________ TestOverrideProvider.test_get_resource_filename_no_overrides _________\n\nself = <r2e_tests.test_config.test_assets.TestOverrideProvider testMethod=test_get_resource_filename_no_overrides>\n\n    def test_get_resource_filename_no_overrides(self):\n        resource_name = 'test_assets.py'\n        import pyramid.tests.test_config\n        provider = self._makeOne(pyramid.tests.test_config)\n        expected = os.path.join(here, resource_name)\n        result = provider.get_resource_filename(None, resource_name)\n>       self.assertEqual(result, expected)\nE       AssertionError: '/hom[73 chars]faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py' != '/hom[73 chars]faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:297: AssertionError\n____ TestOverrideProvider.test_get_resource_filename_override_returns_None _____\n\nself = <r2e_tests.test_config.test_assets.TestOverrideProvider testMethod=test_get_resource_filename_override_returns_None>\n\n    def test_get_resource_filename_override_returns_None(self):\n        overrides = DummyOverrides(None)\n        self._registerOverrides(overrides)\n        resource_name = 'test_assets.py'\n        import pyramid.tests.test_config\n        provider = self._makeOne(pyramid.tests.test_config)\n        expected = os.path.join(here, resource_name)\n        result = provider.get_resource_filename(None, resource_name)\n>       self.assertEqual(result, expected)\nE       AssertionError: '/hom[73 chars]faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py' != '/hom[73 chars]faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:345: AssertionError\n___________________ TestPackageAssetSource.test_get_filename ___________________\n\nself = <r2e_tests.test_config.test_assets.TestPackageAssetSource testMethod=test_get_filename>\n\n    def test_get_filename(self):\n        source = self._makeOne('')\n>       self.assertEqual(source.get_filename('test_assets.py'),\n                         os.path.join(here, 'test_assets.py'))\nE       AssertionError: '/hom[73 chars]faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py' != '/hom[73 chars]faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:716: AssertionError\n_____________ TestPackageAssetSource.test_get_filename_with_prefix _____________\n\nself = <r2e_tests.test_config.test_assets.TestPackageAssetSource testMethod=test_get_filename_with_prefix>\n\n    def test_get_filename_with_prefix(self):\n        source = self._makeOne('test_assets.py')\n>       self.assertEqual(source.get_filename(''),\n                         os.path.join(here, 'test_assets.py'))\nE       AssertionError: '/hom[73 chars]faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py' != '/hom[73 chars]faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py'\nE       - /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/test_assets.py\nE       ?                                                                                                    -- ^^^^^\nE       + /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/test_config/test_assets.py\nE       ?                                                                                                     ^^^\n\nr2e_tests/test_config/test_assets.py:721: AssertionError\n_________ TestI18NConfiguratorMixin.test_add_translation_dirs_abspath __________\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_abspath>\n\n    def test_add_translation_dirs_abspath(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n>       config.add_translation_dirs(locale)\n\nr2e_tests/test_config/test_i18n.py:86: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \npyramid/util.py:573: in wrapper\n    result = wrapped(self, *arg, **kw)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <pyramid.config.Configurator object at 0x7581028e2220>\nspecs = ('/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale',)\nintrospectables = []\nspec = '/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale'\npackage_name = None\n\n    @action_method\n    def add_translation_dirs(self, *specs):\n        \"\"\" Add one or more :term:`translation directory` paths to the\n        current configuration state.  The ``specs`` argument is a\n        sequence that may contain absolute directory paths\n        (e.g. ``/usr/share/locale``) or :term:`asset specification`\n        names naming a directory path (e.g. ``some.package:locale``)\n        or a combination of the two.\n    \n        Example:\n    \n        .. code-block:: python\n    \n           config.add_translation_dirs('/usr/share/locale',\n                                       'some.package:locale')\n    \n        Later calls to ``add_translation_dir`` insert directories into the\n        beginning of the list of translation directories created by earlier\n        calls.  This means that the same translation found in a directory\n        added later in the configuration process will be found before one\n        added earlier in the configuration process.  However, if multiple\n        specs are provided in a single call to ``add_translation_dirs``, the\n        directories will be inserted into the beginning of the directory list\n        in the order they're provided in the ``*specs`` list argument (items\n        earlier in the list trump ones later in the list).\n        \"\"\"\n        directories = []\n        introspectables = []\n    \n        for spec in specs[::-1]: # reversed\n            package_name, filename = self._split_spec(spec)\n            if package_name is None: # absolute filename\n                directory = filename\n            else:\n                __import__(package_name)\n                package = sys.modules[package_name]\n                directory = os.path.join(package_path(package), filename)\n    \n            if not os.path.isdir(os.path.realpath(directory)):\n>               raise ConfigurationError('\"%s\" is not a directory' %\n                                         directory)\nE               pyramid.exceptions.ConfigurationError: \"/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale\" is not a directory\n\npyramid/config/i18n.py:86: ConfigurationError\n________ TestI18NConfiguratorMixin.test_add_translation_dirs_asset_spec ________\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_asset_spec>\n\n    def test_add_translation_dirs_asset_spec(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale')\n>       self.assertEqual(config.registry.getUtility(ITranslationDirectories),\n                         [locale])\nE       AssertionError: Lists differ: ['/ho[70 chars]c5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale'] != ['/ho[70 chars]c5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale']\nE       \nE       First differing element 0:\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale'\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale'\nE       \nE       - ['/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale']\nE       ?                                                                                                      -- ^^^^^\nE       \nE       + ['/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale']\nE       ?                                                                                                       ^^^\n\nr2e_tests/test_config/test_i18n.py:54: AssertionError\n_ TestI18NConfiguratorMixin.test_add_translation_dirs_asset_spec_existing_translation_dirs _\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_asset_spec_existing_translation_dirs>\n\n    def test_add_translation_dirs_asset_spec_existing_translation_dirs(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n        directories = ['abc']\n        config.registry.registerUtility(directories, ITranslationDirectories)\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale')\n        result = config.registry.getUtility(ITranslationDirectories)\n>       self.assertEqual(result, [locale, 'abc'])\nE       AssertionError: Lists differ: ['/ho[77 chars]afa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale', 'abc'] != ['/ho[77 chars]afa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale', 'abc']\nE       \nE       First differing element 0:\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale'\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale'\nE       \nE       - ['/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale',\nE       ?                                                                                                      -- ^^^^^\nE       \nE       + ['/home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale',\nE       ?                                                                                                       ^^^\nE       \nE          'abc']\n\nr2e_tests/test_config/test_i18n.py:64: AssertionError\n______ TestI18NConfiguratorMixin.test_add_translation_dirs_multiple_specs ______\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_multiple_specs>\n\n    def test_add_translation_dirs_multiple_specs(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale',\n                                    'pyramid.tests.pkgs.localeapp:locale2')\n>       self.assertEqual(config.registry.getUtility(ITranslationDirectories),\n                         [locale, locale2])\nE       AssertionError: Lists differ: ['/ho[91 chars]d31f/pyramid/tests/pkgs/localeapp/locale', '/h[130 chars]le2'] != ['/ho[91 chars]d31f/r2e_tests/pkgs/localeapp/locale', '/home/[122 chars]le2']\nE       \nE       First differing element 0:\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale'\nE       '/hom[68 chars]ec5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale'\nE       \nE       Diff is 1002 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_config/test_i18n.py:71: AssertionError\n_ TestI18NConfiguratorMixin.test_add_translation_dirs_multiple_specs_multiple_calls _\n\nself = <r2e_tests.test_config.test_i18n.TestI18NConfiguratorMixin testMethod=test_add_translation_dirs_multiple_specs_multiple_calls>\n\n    def test_add_translation_dirs_multiple_specs_multiple_calls(self):\n        from pyramid.interfaces import ITranslationDirectories\n        config = self._makeOne(autocommit=True)\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale',\n                                    'pyramid.tests.pkgs.localeapp:locale2')\n        config.add_translation_dirs('pyramid.tests.pkgs.localeapp:locale3')\n>       self.assertEqual(config.registry.getUtility(ITranslationDirectories),\n                         [locale3, locale, locale2])\nE       AssertionError: Lists differ: ['/ho[91 chars]d31f/pyramid/tests/pkgs/localeapp/locale3', '/[269 chars]le2'] != ['/ho[91 chars]d31f/r2e_tests/pkgs/localeapp/locale3', '/home[257 chars]le2']\nE       \nE       First differing element 0:\nE       '/hom[69 chars]c5a3faeafa5aee60757c6d31f/pyramid/tests/pkgs/localeapp/locale3'\nE       '/hom[69 chars]c5a3faeafa5aee60757c6d31f/r2e_tests/pkgs/localeapp/locale3'\nE       \nE       Diff is 1504 characters long. Set self.maxDiff to None to see it.\n\nr2e_tests/test_config/test_i18n.py:80: AssertionError\n___________________ ConfiguratorTests.test_ctor_no_registry ____________________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_ctor_no_registry>\n\n    def test_ctor_no_registry(self):\n        import sys\n        from pyramid.interfaces import ISettings\n        from pyramid.config import Configurator\n        from pyramid.interfaces import IRendererFactory\n        config = Configurator()\n        this_pkg = sys.modules['pyramid.tests.test_config']\n        self.assertTrue(config.registry.getUtility(ISettings))\n>       self.assertEqual(config.package, this_pkg)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:68: AssertionError\n_________ ConfiguratorTests.test_ctor_noreg_debug_logger_None_default __________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_ctor_noreg_debug_logger_None_default>\n\n    def test_ctor_noreg_debug_logger_None_default(self):\n        from pyramid.interfaces import IDebugLogger\n        config = self._makeOne()\n        logger = config.registry.getUtility(IDebugLogger)\n>       self.assertEqual(logger.name, 'pyramid.tests.test_config')\nE       AssertionError: 'r2e_tests.test_config' != 'pyramid.tests.test_config'\nE       - r2e_tests.test_config\nE       ?  ^^^\nE       + pyramid.tests.test_config\nE       ? ++ ^^^^^\n\nr2e_tests/test_config/test_init.py:124: AssertionError\n_____________ ConfiguratorTests.test_include_constant_root_package _____________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_include_constant_root_package>\n\n    def test_include_constant_root_package(self):\n        from pyramid import tests\n        from pyramid.tests import test_config\n        config = self._makeOne(root_package=tests)\n        results = {}\n        def include(config):\n            results['package'] = config.package\n            results['root_package'] = config.root_package\n        config.include(include)\n        self.assertEqual(results['root_package'], tests)\n>       self.assertEqual(results['package'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:777: AssertionError\n_______________ ConfiguratorTests.test_scan_integration_conflict _______________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_scan_integration_conflict>\n\n    def test_scan_integration_conflict(self):\n        from pyramid.tests.test_config.pkgs import selfscan\n        from pyramid.config import Configurator\n        c = Configurator()\n        c.scan(selfscan)\n        c.scan(selfscan)\n        try:\n>           c.commit()\n\nr2e_tests/test_config/test_init.py:1039: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \npyramid/config/__init__.py:654: in commit\n    self.action_state.execute_actions(introspector=self.introspector)\npyramid/config/__init__.py:1163: in execute_actions\n    action = next(pending_actions, None)\npyramid/config/__init__.py:1121: in resume\n    for a, b in zip_longest(actions, executed_actions):\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nactions = [{'args': (), 'callable': <function ViewsConfiguratorMixin.add_view.<locals>.register at 0x758102129700>, 'discriminat...8102129c10>, 'discriminator': ('view', None, 'two', None, 'd41d8cd98f00b204e9800998ecf8427e'), 'includepath': (), ...}]\n\n    def resolveConflicts(actions):\n        \"\"\"Resolve conflicting actions\n    \n        Given an actions list, identify and try to resolve conflicting actions.\n        Actions conflict if they have the same non-None discriminator.\n        Conflicting actions can be resolved if the include path of one of\n        the actions is a prefix of the includepaths of the other\n        conflicting actions and is unequal to the include paths in the\n        other conflicting actions.\n        \"\"\"\n    \n        def orderandpos(v):\n            n, v = v\n            if not isinstance(v, dict):\n                # old-style tuple action\n                v = expand_action(*v)\n            return (v['order'] or 0, n)\n    \n        sactions = sorted(enumerate(actions), key=orderandpos)\n    \n        def orderonly(v):\n            n, v = v\n            if not isinstance(v, dict):\n                # old-style tuple action\n                v = expand_action(*v)\n            return v['order'] or 0\n    \n        for order, actiongroup in itertools.groupby(sactions, orderonly):\n            # \"order\" is an integer grouping. Actions in a lower order will be\n            # executed before actions in a higher order.  All of the actions in\n            # one grouping will be executed (its callable, if any will be called)\n            # before any of the actions in the next.\n    \n            unique = {}\n            output = []\n    \n            for i, action in actiongroup:\n                # Within an order, actions are executed sequentially based on\n                # original action ordering (\"i\").\n    \n                if not isinstance(action, dict):\n                    # old-style tuple action\n                    action = expand_action(*action)\n    \n                # \"ainfo\" is a tuple of (order, i, action) where \"order\" is a\n                # user-supplied grouping, \"i\" is an integer expressing the relative\n                # position of this action in the action list being resolved, and\n                # \"action\" is an action dictionary.  The purpose of an ainfo is to\n                # associate an \"order\" and an \"i\" with a particular action; \"order\"\n                # and \"i\" exist for sorting purposes after conflict resolution.\n                ainfo = (order, i, action)\n    \n                discriminator = undefer(action['discriminator'])\n                action['discriminator'] = discriminator\n    \n                if discriminator is None:\n                    # The discriminator is None, so this action can never conflict.\n                    # We can add it directly to the result.\n                    output.append(ainfo)\n                    continue\n    \n                L = unique.setdefault(discriminator, [])\n                L.append(ainfo)\n    \n            # Check for conflicts\n            conflicts = {}\n    \n            for discriminator, ainfos in unique.items():\n                # We use (includepath, order, i) as a sort key because we need to\n                # sort the actions by the paths so that the shortest path with a\n                # given prefix comes first.  The \"first\" action is the one with the\n                # shortest include path.  We break sorting ties using \"order\", then\n                # \"i\".\n                def bypath(ainfo):\n                    path, order, i = ainfo[2]['includepath'], ainfo[0], ainfo[1]\n                    return path, order, i\n    \n                ainfos.sort(key=bypath)\n                ainfo, rest = ainfos[0], ainfos[1:]\n                output.append(ainfo)\n                _, _, action = ainfo\n                basepath, baseinfo, discriminator = (\n                    action['includepath'],\n                    action['info'],\n                    action['discriminator'],\n                    )\n    \n                for _, _, action in rest:\n                    includepath = action['includepath']\n                    # Test whether path is a prefix of opath\n                    if (includepath[:len(basepath)] != basepath or  # not a prefix\n                            includepath == basepath):\n                        L = conflicts.setdefault(discriminator, [baseinfo])\n                        L.append(action['info'])\n    \n            if conflicts:\n>               raise ConfigurationConflictError(conflicts)\nE               pyramid.exceptions.ConfigurationConflictError: Conflicting configuration actions\nE                 For: ('view', None, '', None, 'd41d8cd98f00b204e9800998ecf8427e')\nE                   Line 4 of file /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/selfscan/__init__.py:\nE                       def abc(request):\nE                   Line 4 of file /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/selfscan/__init__.py:\nE                       def abc(request):\nE                 For: ('view', None, 'two', None, 'd41d8cd98f00b204e9800998ecf8427e')\nE                   Line 4 of file /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/selfscan/another.py:\nE                       def two(request):\nE                   Line 4 of file /home/gcpuser/buckets/local_repoeval_bucket/repos/pyramid_c231d8174e811eec5a3faeafa5aee60757c6d31f/pyramid/tests/test_config/pkgs/selfscan/another.py:\nE                       def two(request):\n\npyramid/config/__init__.py:1299: ConfigurationConflictError\n\nDuring handling of the above exception, another exception occurred:\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_scan_integration_conflict>\n\n    def test_scan_integration_conflict(self):\n        from pyramid.tests.test_config.pkgs import selfscan\n        from pyramid.config import Configurator\n        c = Configurator()\n        c.scan(selfscan)\n        c.scan(selfscan)\n        try:\n            c.commit()\n        except ConfigurationConflictError as why:\n            def scanconflicts(e):\n                conflicts = e._conflicts.values()\n                for conflict in conflicts:\n                    for confinst in conflict:\n                        yield confinst.src\n            which = list(scanconflicts(why))\n            self.assertEqual(len(which), 4)\n>           self.assertTrue(\"@view_config(renderer='string')\" in which)\nE           AssertionError: False is not true\n\nr2e_tests/test_config/test_init.py:1048: AssertionError\n_______ ConfiguratorTests.test_setup_registry_debug_logger_None_default ________\n\nself = <r2e_tests.test_config.test_init.ConfiguratorTests testMethod=test_setup_registry_debug_logger_None_default>\n\n    def test_setup_registry_debug_logger_None_default(self):\n        from pyramid.registry import Registry\n        from pyramid.interfaces import IDebugLogger\n        reg = Registry()\n        config = self._makeOne(reg)\n        config.setup_registry()\n        logger = reg.getUtility(IDebugLogger)\n>       self.assertEqual(logger.name, 'pyramid.tests.test_config')\nE       AssertionError: 'r2e_tests.test_config' != 'pyramid.tests.test_config'\nE       - r2e_tests.test_config\nE       ?  ^^^\nE       + pyramid.tests.test_config\nE       ? ++ ^^^^^\n\nr2e_tests/test_config/test_init.py:444: AssertionError\n____ TestConfigurator_add_directive.test_add_directive_with_custom_callable ____\n\nself = <r2e_tests.test_config.test_init.TestConfigurator_add_directive testMethod=test_add_directive_with_custom_callable>\n\n    def test_add_directive_with_custom_callable(self):\n        from pyramid.tests import test_config\n        config = self.config\n        config.add_directive(\n                'dummy_callable', 'pyramid.tests.test_config.dummy_callable')\n        self.assertTrue(hasattr(config, 'dummy_callable'))\n        config.dummy_callable('discrim')\n        after = config.action_state\n        action = after.actions[-1]\n        self.assertEqual(action['discriminator'], 'discrim')\n        self.assertEqual(action['callable'], None)\n>       self.assertEqual(action['args'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:1247: AssertionError\n________ TestConfigurator_add_directive.test_add_directive_with_partial ________\n\nself = <r2e_tests.test_config.test_init.TestConfigurator_add_directive testMethod=test_add_directive_with_partial>\n\n    def test_add_directive_with_partial(self):\n        from pyramid.tests import test_config\n        config = self.config\n        config.add_directive(\n                'dummy_partial', 'pyramid.tests.test_config.dummy_partial')\n        self.assertTrue(hasattr(config, 'dummy_partial'))\n        config.dummy_partial()\n        after = config.action_state\n        action = after.actions[-1]\n        self.assertEqual(action['discriminator'], 'partial')\n        self.assertEqual(action['callable'], None)\n>       self.assertEqual(action['args'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:1234: AssertionError\n_________ TestConfigurator_add_directive.test_extend_with_dotted_name __________\n\nself = <r2e_tests.test_config.test_init.TestConfigurator_add_directive testMethod=test_extend_with_dotted_name>\n\n    def test_extend_with_dotted_name(self):\n        from pyramid.tests import test_config\n        config = self.config\n        config.add_directive(\n            'dummy_extend', 'pyramid.tests.test_config.dummy_extend')\n        self.assertTrue(hasattr(config, 'dummy_extend'))\n        config.dummy_extend('discrim')\n        after = config.action_state\n        action = after.actions[-1]\n        self.assertEqual(action['discriminator'], 'discrim')\n        self.assertEqual(action['callable'], None)\n>       self.assertEqual(action['args'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:1221: AssertionError\n_______ TestConfigurator_add_directive.test_extend_with_python_callable ________\n\nself = <r2e_tests.test_config.test_init.TestConfigurator_add_directive testMethod=test_extend_with_python_callable>\n\n    def test_extend_with_python_callable(self):\n        from pyramid.tests import test_config\n        config = self.config\n        config.add_directive(\n            'dummy_extend', dummy_extend)\n        self.assertTrue(hasattr(config, 'dummy_extend'))\n        config.dummy_extend('discrim')\n        after = config.action_state\n        action = after.actions[-1]\n        self.assertEqual(action['discriminator'], 'discrim')\n        self.assertEqual(action['callable'], None)\n>       self.assertEqual(action['args'], test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_init.py:1260: AssertionError\n_________ TestConfigurator__add_predicate.test_factory_as_dotted_name __________\n\nself = <r2e_tests.test_config.test_init.TestConfigurator__add_predicate testMethod=test_factory_as_dotted_name>\n\n    def test_factory_as_dotted_name(self):\n        config = self._makeOne()\n    \n        def _fakeAction(discriminator, callable=None, args=(),\n                        kw=None, order=0, introspectables=(), **extra):\n            self.assertEqual(len(introspectables), 1)\n            self.assertEqual(introspectables[0]['name'], 'testing')\n            self.assertEqual(introspectables[0]['factory'], DummyPredicate)\n    \n        config.action = _fakeAction\n>       config._add_predicate(\n            'route',\n            'testing',\n            'pyramid.tests.test_config.test_init.DummyPredicate'\n            )\n\nr2e_tests/test_config/test_init.py:1324: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \npyramid/config/__init__.py:543: in _add_predicate\n    self.action(discriminator, register, introspectables=(intr,),\nr2e_tests/test_config/test_init.py:1321: in _fakeAction\n    self.assertEqual(introspectables[0]['factory'], DummyPredicate)\nE   AssertionError: <class 'pyramid.tests.test_config.test_init.DummyPredicate'> != <class 'r2e_tests.test_config.test_init.DummyPredicate'>\n____ TestViewsConfigurationMixin.test_add_static_view_package_here_relative ____\n\nself = <r2e_tests.test_config.test_views.TestViewsConfigurationMixin testMethod=test_add_static_view_package_here_relative>\n\n    def test_add_static_view_package_here_relative(self):\n        from pyramid.interfaces import IStaticURLInfo\n        info = DummyStaticURLInfo()\n        config = self._makeOne(autocommit=True)\n        config.registry.registerUtility(info, IStaticURLInfo)\n        config.add_static_view('static', 'files')\n>       self.assertEqual(\n            info.added,\n            [(config, 'static', 'pyramid.tests.test_config:files', {})])\nE       AssertionError: Lists differ: [(<py[39 chars]5810219c0a0>, 'static', 'r2e_tests.test_config:files', {})] != [(<py[39 chars]5810219c0a0>, 'static', 'pyramid.tests.test_config:files', {})]\nE       \nE       First differing element 0:\nE       (<pyr[37 chars]75810219c0a0>, 'static', 'r2e_tests.test_config:files', {})\nE       (<pyr[37 chars]75810219c0a0>, 'static', 'pyramid.tests.test_config:files', {})\nE       \nE         [(<pyramid.config.Configurator object at 0x75810219c0a0>,\nE           'static',\nE       -   'r2e_tests.test_config:files',\nE       ?     ^^^\nE       \nE       +   'pyramid.tests.test_config:files',\nE       ?    ++ ^^^^^\nE       \nE           {})]\n\nr2e_tests/test_config/test_views.py:1842: AssertionError\n_______ TestViewsConfigurationMixin.test_add_view_with_template_renderer _______\n\nself = <r2e_tests.test_config.test_views.TestViewsConfigurationMixin testMethod=test_add_view_with_template_renderer>\n\n    def test_add_view_with_template_renderer(self):\n        from pyramid.tests import test_config\n        from pyramid.interfaces import ISettings\n        class view(object):\n            def __init__(self, context, request):\n                self.request = request\n                self.context = context\n    \n            def __call__(self):\n                return {'a':'1'}\n        config = self._makeOne(autocommit=True)\n        renderer = self._registerRenderer(config)\n        fixture = 'pyramid.tests.test_config:files/minimal.txt'\n        config.introspection = False\n        config.add_view(view=view, renderer=fixture)\n        wrapper = self._getViewCallable(config)\n        request = self._makeRequest(config)\n        result = wrapper(None, request)\n        self.assertEqual(result.body, b'Hello!')\n        settings = config.registry.queryUtility(ISettings)\n        result = renderer.info\n        self.assertEqual(result.registry, config.registry)\n        self.assertEqual(result.type, '.txt')\n>       self.assertEqual(result.package, test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_views.py:1143: AssertionError\n_ TestViewsConfigurationMixin.test_add_view_with_template_renderer_no_callable _\n\nself = <r2e_tests.test_config.test_views.TestViewsConfigurationMixin testMethod=test_add_view_with_template_renderer_no_callable>\n\n    def test_add_view_with_template_renderer_no_callable(self):\n        from pyramid.tests import test_config\n        from pyramid.interfaces import ISettings\n        config = self._makeOne(autocommit=True)\n        renderer = self._registerRenderer(config)\n        fixture = 'pyramid.tests.test_config:files/minimal.txt'\n        config.introspection = False\n        config.add_view(view=None, renderer=fixture)\n        wrapper = self._getViewCallable(config)\n        request = self._makeRequest(config)\n        result = wrapper(None, request)\n        self.assertEqual(result.body, b'Hello!')\n        settings = config.registry.queryUtility(ISettings)\n        result = renderer.info\n        self.assertEqual(result.registry, config.registry)\n        self.assertEqual(result.type, '.txt')\n>       self.assertEqual(result.package, test_config)\nE       AssertionError: <module 'r2e_tests.test_config' from '/home/gcpuse[117 chars].py'> != <module 'pyramid.tests.test_config' from '/home/gc[125 chars].py'>\n\nr2e_tests/test_config/test_views.py:1184: AssertionError\n_________ TestStaticURLInfo.test_generate_url_cachebust_with_overrides _________\n\nself = <r2e_tests.test_config.test_views.TestStaticURLInfo testMethod=test_generate_url_cachebust_with_overrides>\n\n    def test_generate_url_cachebust_with_overrides(self):\n        config = testing.setUp()\n        try:\n            request = testing.DummyRequest()\n            config.add_static_view('static', 'path')\n            config.override_asset(\n                'pyramid.tests.test_config:path/',\n                'pyramid.tests.test_config:other_path/')\n            def cb(val):\n                def cb_(request, subpath, kw):\n                    kw['_query'] = {'x': val}\n                    return subpath, kw\n                return cb_\n            config.add_cache_buster('path', cb('foo'))\n            result = request.static_url('path/foo.png')\n            self.assertEqual(result, 'http://example.com/static/foo.png?x=foo')\n            config.add_cache_buster('other_path', cb('bar'), explicit=True)\n            result = request.static_url('path/foo.png')\n>           self.assertEqual(result, 'http://example.com/static/foo.png?x=bar')\nE           AssertionError: 'http://example.com/static/foo.png?x=foo' != 'http://example.com/static/foo.png?x=bar'\nE           - http://example.com/static/foo.png?x=foo\nE           ?                                     ^^^\nE           + http://example.com/static/foo.png?x=bar\nE           ?                                     ^^^\n\nr2e_tests/test_config/test_views.py:2921: AssertionError\n___________________ Test_view_description.test_without_text ____________________\n\nself = <r2e_tests.test_config.test_views.Test_view_description testMethod=test_without_text>\n\n    def test_without_text(self):\n        def view(): pass\n        result = self._callFUT(view)\n>       self.assertEqual(result,\n                         'function pyramid.tests.test_config.test_views.view')\nE       AssertionError: 'function r2e_tests.test_config.test_views.view' != 'function pyramid.tests.test_config.test_views.view'\nE       - function r2e_tests.test_config.test_views.view\nE       ?           ^^^\nE       + function pyramid.tests.test_config.test_views.view\nE       ?          ++ ^^^^^\n\nr2e_tests/test_config/test_views.py:3092: AssertionError\n_______________ TestPRequestCommand.test_command_display_headers _______________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_display_headers>\n\n    def test_command_display_headers(self):\n        command = self._makeOne(\n            ['', '--display-headers', 'development.ini', '/'])\n        command.run()\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(\n            self._out,\n            ['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc'])\nE       AssertionError: Lists differ: ['200 OK', b'abc'] != ['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc']\nE       \nE       First differing element 1:\nE       b'abc'\nE       'Content-Type: text/html; charset=UTF-8'\nE       \nE       Second list contains 1 additional elements.\nE       First extra element 2:\nE       'abc'\nE       \nE       - ['200 OK', b'abc']\nE       + ['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc']\n\nr2e_tests/test_scripts/test_prequest.py:202: AssertionError\n_________ TestPRequestCommand.test_command_has_content_type_header_var _________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_has_content_type_header_var>\n\n    def test_command_has_content_type_header_var(self):\n        command = self._makeOne(\n            ['', '--header=content-type:app/foo','development.ini', '/'])\n        command.run()\n        self.assertEqual(self._environ['CONTENT_TYPE'], 'app/foo')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:92: AssertionError\n_____________ TestPRequestCommand.test_command_has_good_header_var _____________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_has_good_header_var>\n\n    def test_command_has_good_header_var(self):\n        command = self._makeOne(\n            ['', '--header=name:value','development.ini', '/'])\n        command.run()\n        self.assertEqual(self._environ['HTTP_NAME'], 'value')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:69: AssertionError\n__________ TestPRequestCommand.test_command_has_multiple_header_vars ___________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_has_multiple_header_vars>\n\n    def test_command_has_multiple_header_vars(self):\n        command = self._makeOne(\n            ['',\n             '--header=name:value',\n             '--header=name2:value2',\n             'development.ini',\n             '/'])\n        command.run()\n        self.assertEqual(self._environ['HTTP_NAME'], 'value')\n        self.assertEqual(self._environ['HTTP_NAME2'], 'value2')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:107: AssertionError\n_________________ TestPRequestCommand.test_command_method_get __________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_get>\n\n    def test_command_method_get(self):\n        command = self._makeOne(['', '--method=GET', 'development.ini', '/'])\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'GET')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:116: AssertionError\n_______________ TestPRequestCommand.test_command_method_options ________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_options>\n\n    def test_command_method_options(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=OPTIONS', 'development.ini',\n                                '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'OPTIONS')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:184: AssertionError\n________________ TestPRequestCommand.test_command_method_patch _________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_patch>\n\n    def test_command_method_patch(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=PATCH', 'development.ini', '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'PATCH')\n        self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')\n        self.assertEqual(self._environ['wsgi.input'], stdin)\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:158: AssertionError\n_________________ TestPRequestCommand.test_command_method_post _________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_post>\n\n    def test_command_method_post(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=POST', 'development.ini', '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'POST')\n        self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')\n        self.assertEqual(self._environ['wsgi.input'], stdin)\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:130: AssertionError\n_______________ TestPRequestCommand.test_command_method_propfind _______________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_propfind>\n\n    def test_command_method_propfind(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=PROPFIND', 'development.ini',\n                                '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'PROPFIND')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:171: AssertionError\n_________________ TestPRequestCommand.test_command_method_put __________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_method_put>\n\n    def test_command_method_put(self):\n        from pyramid.compat import NativeIO\n        command = self._makeOne(['', '--method=PUT', 'development.ini', '/'])\n        stdin = NativeIO()\n        command.stdin = stdin\n        command.run()\n        self.assertEqual(self._environ['REQUEST_METHOD'], 'PUT')\n        self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')\n        self.assertEqual(self._environ['wsgi.input'], stdin)\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:144: AssertionError\n________ TestPRequestCommand.test_command_path_doesnt_start_with_slash _________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_path_doesnt_start_with_slash>\n\n    def test_command_path_doesnt_start_with_slash(self):\n        command = self._makeOne(['', 'development.ini', 'abc'])\n        command.run()\n        self.assertEqual(self._path_info, '/abc')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:50: AssertionError\n__________________ TestPRequestCommand.test_command_two_args ___________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_two_args>\n\n    def test_command_two_args(self):\n        command = self._makeOne(['', 'development.ini', '/'])\n        command.run()\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:42: AssertionError\n________________ TestPRequestCommand.test_command_w_basic_auth _________________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_w_basic_auth>\n\n    def test_command_w_basic_auth(self):\n        command = self._makeOne(\n            ['', '--login=user:password',\n                 '--header=name:value','development.ini', '/'])\n        command.run()\n        self.assertEqual(self._environ['HTTP_NAME'], 'value')\n        self.assertEqual(self._environ['HTTP_AUTHORIZATION'],\n                        'Basic dXNlcjpwYXNzd29yZA==')\n        self.assertEqual(self._path_info, '/')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:82: AssertionError\n______________ TestPRequestCommand.test_command_with_query_string ______________\n\nself = <r2e_tests.test_scripts.test_prequest.TestPRequestCommand testMethod=test_command_with_query_string>\n\n    def test_command_with_query_string(self):\n        command = self._makeOne(['', 'development.ini', '/abc?a=1&b=2&c'])\n        command.run()\n        self.assertEqual(self._environ['QUERY_STRING'], 'a=1&b=2&c')\n        self.assertEqual(self._path_info, '/abc')\n        self.assertEqual(self._spec, 'development.ini')\n        self.assertEqual(self._app_name, None)\n>       self.assertEqual(self._out, ['abc'])\nE       AssertionError: Lists differ: [b'abc'] != ['abc']\nE       \nE       First differing element 0:\nE       b'abc'\nE       'abc'\nE       \nE       - [b'abc']\nE       ?  -\nE       \nE       + ['abc']\n\nr2e_tests/test_scripts/test_prequest.py:193: AssertionError\n_______________ TestPRoutesCommand.test_config_format_ini_commas _______________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_config_format_ini_commas>\n\n    def test_config_format_ini_commas(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n    \n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        config_factory = dummy.DummyConfigParserFactory()\n        command.ConfigParser = config_factory\n        config_factory.items = [('format', 'method,name')]\n    \n        result = command.run()\n>       self.assertEqual(result, 0)\nE       AssertionError: 2 != 0\n\nr2e_tests/test_scripts/test_proutes.py:726: AssertionError\n______________ TestPRoutesCommand.test_config_format_ini_newlines ______________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_config_format_ini_newlines>\n\n    def test_config_format_ini_newlines(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n    \n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        config_factory = dummy.DummyConfigParserFactory()\n        command.ConfigParser = config_factory\n        config_factory.items = [('format', 'method\\nname')]\n    \n        result = command.run()\n>       self.assertEqual(result, 0)\nE       AssertionError: 2 != 0\n\nr2e_tests/test_scripts/test_proutes.py:660: AssertionError\n_______________ TestPRoutesCommand.test_config_format_ini_spaces _______________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_config_format_ini_spaces>\n\n    def test_config_format_ini_spaces(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n    \n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        config_factory = dummy.DummyConfigParserFactory()\n        command.ConfigParser = config_factory\n        config_factory.items = [('format', 'method name')]\n    \n        result = command.run()\n>       self.assertEqual(result, 0)\nE       AssertionError: 2 != 0\n\nr2e_tests/test_scripts/test_proutes.py:693: AssertionError\n_________ TestPRoutesCommand.test_one_route_all_methods_view_only_post _________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_one_route_all_methods_view_only_post>\n\n    def test_one_route_all_methods_view_only_post(self):\n        from pyramid.renderers import null_renderer as nr\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method='POST'\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1', 'POST'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:309: AssertionError\n_________ TestPRoutesCommand.test_one_route_only_post_view_all_methods _________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_one_route_only_post_view_all_methods>\n\n    def test_one_route_only_post_view_all_methods(self):\n        from pyramid.renderers import null_renderer as nr\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b', request_method='POST')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1', 'POST'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:336: AssertionError\n________ TestPRoutesCommand.test_one_route_only_post_view_post_and_get _________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_one_route_only_post_view_post_and_get>\n\n    def test_one_route_only_post_view_post_and_get(self):\n        from pyramid.renderers import null_renderer as nr\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b', request_method='POST')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=('POST', 'GET')\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1', 'POST'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'POST']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:364: AssertionError\n_____ TestPRoutesCommand.test_one_route_with_long_name_one_view_registered _____\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_one_route_with_long_name_one_view_registered>\n\n    def test_one_route_with_long_name_one_view_registered(self):\n        from zope.interface import Interface\n        from pyramid.interfaces import IRouteRequest\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import IView\n        registry = self._makeRegistry()\n    \n        def view():pass\n    \n        class IMyRoute(Interface):\n            pass\n    \n        registry.registerAdapter(\n            view,\n            (IViewClassifier, IMyRoute, Interface),\n            IView, ''\n        )\n    \n        registry.registerUtility(IMyRoute, IRouteRequest,\n                                 name='very_long_name_123')\n    \n        command = self._makeOne()\n        route = dummy.DummyRoute(\n            'very_long_name_123',\n            '/and_very_long_pattern_as_well'\n        )\n        mapper = dummy.DummyMapper(route)\n        command._get_mapper = lambda *arg: mapper\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()[:3]\n>       self.assertEqual(\n            compare_to,\n            ['very_long_name_123',\n             '/and_very_long_pattern_as_well',\n             'pyramid.tests.test_scripts.test_proutes.view']\n        )\nE       AssertionError: Lists differ: ['ver[36 chars]ttern_as_well', 'r2e_tests.test_scripts.test_proutes.view'] != ['ver[36 chars]ttern_as_well', 'pyramid.tests.test_scripts.test_proutes.view']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view'\nE       'pyramid.tests.test_scripts.test_proutes.view'\nE       \nE         ['very_long_name_123',\nE          '/and_very_long_pattern_as_well',\nE       -  'r2e_tests.test_scripts.test_proutes.view']\nE       ?    ^^^\nE       \nE       +  'pyramid.tests.test_scripts.test_proutes.view']\nE       ?   ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:195: AssertionError\n______ TestPRoutesCommand.test_route_is_get_view_request_method_not_post _______\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_route_is_get_view_request_method_not_post>\n\n    def test_route_is_get_view_request_method_not_post(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b', request_method='GET')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1',\n            'GET'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'GET'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'GET']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', 'GET']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', 'GET']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:503: AssertionError\n____________ TestPRoutesCommand.test_route_request_method_mismatch _____________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_route_request_method_mismatch>\n\n    def test_route_request_method_mismatch(self):\n        from pyramid.renderers import null_renderer as nr\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b', request_method='POST')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method='GET'\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1',\n            '<route', 'mismatch>'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1[20 chars]ch>'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.v[24 chars]ch>']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE         ['foo',\nE          '/a/b',\nE       -  'r2e_tests.test_scripts.test_proutes.view1',\nE       ?    ^^^\nE       \nE       +  'pyramid.tests.test_scripts.test_proutes.view1',\nE       ?   ++ ^^^^^\nE       \nE          '<route',\nE          'mismatch>']\n\nr2e_tests/test_scripts/test_proutes.py:393: AssertionError\n__________________ TestPRoutesCommand.test_route_static_views __________________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_route_static_views>\n\n    def test_route_static_views(self):\n        from pyramid.renderers import null_renderer as nr\n        config = self._makeConfig(autocommit=True)\n        config.add_static_view('static', 'static', cache_max_age=3600)\n        config.add_static_view(name='static2', path='/var/www/static')\n        config.add_static_view(\n            name='pyramid_scaffold',\n            path='pyramid:scaffolds/starter/+package+/static'\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 5)\n    \n        expected = [\n            ['__static/', '/static/*subpath',\n             'pyramid.tests.test_scripts:static/', '*'],\n            ['__static2/', '/static2/*subpath', '/var/www/static/', '*'],\n            ['__pyramid_scaffold/', '/pyramid_scaffold/*subpath',\n             'pyramid:scaffolds/starter/+package+/static/',  '*'],\n        ]\n    \n        for index, line in enumerate(L[2:]):\n            data = line.split()\n>           self.assertEqual(data, expected[index])\nE           AssertionError: Lists differ: ['__static/', '/static/*subpath', 'r2e_tests.test_scripts:static/', '*'] != ['__static/', '/static/*subpath', 'pyramid.tests.test_scripts:static/', '*']\nE           \nE           First differing element 2:\nE           'r2e_tests.test_scripts:static/'\nE           'pyramid.tests.test_scripts:static/'\nE           \nE           - ['__static/', '/static/*subpath', 'r2e_tests.test_scripts:static/', '*']\nE           ?                                     ^^^\nE           \nE           + ['__static/', '/static/*subpath', 'pyramid.tests.test_scripts:static/', '*']\nE           ?                                    ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:423: AssertionError\n___________ TestPRoutesCommand.test_single_route_one_view_registered ___________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_single_route_one_view_registered>\n\n    def test_single_route_one_view_registered(self):\n        from zope.interface import Interface\n        from pyramid.interfaces import IRouteRequest\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import IView\n        registry = self._makeRegistry()\n    \n        def view():pass\n        class IMyRoute(Interface):\n            pass\n        registry.registerAdapter(view,\n                                 (IViewClassifier, IMyRoute, Interface),\n                                 IView, '')\n        registry.registerUtility(IMyRoute, IRouteRequest, name='a')\n        command = self._makeOne()\n        route = dummy.DummyRoute('a', '/a')\n        mapper = dummy.DummyMapper(route)\n        command._get_mapper = lambda *arg: mapper\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()[:3]\n>       self.assertEqual(\n            compare_to,\n            ['a', '/a', 'pyramid.tests.test_scripts.test_proutes.view']\n        )\nE       AssertionError: Lists differ: ['a', '/a', 'r2e_tests.test_scripts.test_proutes.view'] != ['a', '/a', 'pyramid.tests.test_scripts.test_proutes.view']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view'\nE       'pyramid.tests.test_scripts.test_proutes.view'\nE       \nE       - ['a', '/a', 'r2e_tests.test_scripts.test_proutes.view']\nE       ?               ^^^\nE       \nE       + ['a', '/a', 'pyramid.tests.test_scripts.test_proutes.view']\nE       ?              ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:155: AssertionError\n______________________ TestPRoutesCommand.test_view_glob _______________________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_view_glob>\n\n    def test_view_glob(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n        def view2(context, request): return 'view2'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        config.add_route('bar', '/b/a')\n        config.add_view(\n            route_name='bar',\n            view=view2,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n        command.options.glob = '*foo*'\n    \n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1',\n            '!POST,*'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', '!POST,*'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', '!POST,*']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', '!POST,*']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', '!POST,*']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:574: AssertionError\n_____________ TestPRoutesCommand.test_view_request_method_not_post _____________\n\nself = <r2e_tests.test_scripts.test_proutes.TestPRoutesCommand testMethod=test_view_request_method_not_post>\n\n    def test_view_request_method_not_post(self):\n        from pyramid.renderers import null_renderer as nr\n        from pyramid.config import not_\n    \n        def view1(context, request): return 'view1'\n    \n        config = self._makeConfig(autocommit=True)\n        config.add_route('foo', '/a/b')\n        config.add_view(\n            route_name='foo',\n            view=view1,\n            renderer=nr,\n            request_method=not_('POST')\n        )\n    \n        command = self._makeOne()\n        L = []\n        command.out = L.append\n        command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(len(L), 3)\n        compare_to = L[-1].split()\n        expected = [\n            'foo', '/a/b',\n            'pyramid.tests.test_scripts.test_proutes.view1',\n            '!POST,*'\n        ]\n>       self.assertEqual(compare_to, expected)\nE       AssertionError: Lists differ: ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', '!POST,*'] != ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', '!POST,*']\nE       \nE       First differing element 2:\nE       'r2e_tests.test_scripts.test_proutes.view1'\nE       'pyramid.tests.test_scripts.test_proutes.view1'\nE       \nE       - ['foo', '/a/b', 'r2e_tests.test_scripts.test_proutes.view1', '!POST,*']\nE       ?                   ^^^\nE       \nE       + ['foo', '/a/b', 'pyramid.tests.test_scripts.test_proutes.view1', '!POST,*']\nE       ?                  ++ ^^^^^\n\nr2e_tests/test_scripts/test_proutes.py:533: AssertionError\n_____ TestPViewsCommand.test_views_command_single_view_function_traversal ______\n\nself = <r2e_tests.test_scripts.test_pviews.TestPViewsCommand testMethod=test_views_command_single_view_function_traversal>\n\n    def test_views_command_single_view_function_traversal(self):\n        from pyramid.registry import Registry\n        registry = Registry()\n        command = self._makeOne(registry=registry)\n        L = []\n        command.out = L.append\n        def view(): pass\n        view.__request_attrs__ = {'context': 'context', 'view_name': 'a'}\n        command._find_view = lambda arg1: view\n        command.args = ('/foo/bar/myapp.ini#myapp', '/a')\n        result = command.run()\n        self.assertEqual(result, 0)\n        self.assertEqual(L[1], 'URL = /a')\n        self.assertEqual(L[3], '    context: context')\n        self.assertEqual(L[4], '    view name: a')\n>       self.assertEqual(L[8],\n                         '    pyramid.tests.test_scripts.test_pviews.view')\nE       AssertionError: '    r2e_tests.test_scripts.test_pviews.view' != '    pyramid.tests.test_scripts.test_pviews.view'\nE       -     r2e_tests.test_scripts.test_pviews.view\nE       ?      ^^^\nE       +     pyramid.tests.test_scripts.test_pviews.view\nE       ?     ++ ^^^^^\n\nr2e_tests/test_scripts/test_pviews.py:296: AssertionError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_function_context_and_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_function_requestonly\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_instance_context_and_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_instance_context_and_request_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_instance_requestonly_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_newstyle_class_context_and_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_newstyle_class_context_and_request_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_newstyle_class_requestonly\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_newstyle_class_requestonly_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_oldstyle_class_context_and_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_oldstyle_class_requestonly\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_oldstyle_cls_context_request_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_as_oldstyle_cls_requestonly_attr_and_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_attr_wrapped_view_branching_default_phash\nPASSED r2e_tests/test_1.py::TestDeriveView::test_attr_wrapped_view_branching_nondefault_phash\nPASSED r2e_tests/test_1.py::TestDeriveView::test_class_with_attr\nPASSED r2e_tests/test_1.py::TestDeriveView::test_class_without_attr\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_denied\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_denied2\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_overridden\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_permitted\nPASSED r2e_tests/test_1.py::TestDeriveView::test_debug_auth_permission_authpol_permitted_no_request\nPASSED r2e_tests/test_1.py::TestDeriveView::test_function_returns_true_Response_no_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_function_returns_true_Response_with_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_prevent_http_cache_in_settings\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_bad_tuple\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_integer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_prevent_auto_set\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_timedelta\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_tuple\nPASSED r2e_tests/test_1.py::TestDeriveView::test_http_cached_view_tuple_seconds_None\nPASSED r2e_tests/test_1.py::TestDeriveView::test_predicate_mismatch_exception_has_text_in_detail\nPASSED r2e_tests/test_1.py::TestDeriveView::test_predicate_mismatch_view_has_name\nPASSED r2e_tests/test_1.py::TestDeriveView::test_predicate_mismatch_view_has_no_name\nPASSED r2e_tests/test_1.py::TestDeriveView::test_requestonly_function\nPASSED r2e_tests/test_1.py::TestDeriveView::test_requestonly_function_with_renderer\nPASSED r2e_tests/test_1.py::TestDeriveView::test_requestonly_function_with_renderer_request_has_view\nPASSED r2e_tests/test_1.py::TestDeriveView::test_requestonly_function_with_renderer_request_override\nPASSED r2e_tests/test_1.py::TestDeriveView::test_secured_view_authn_policy_no_authz_policy\nPASSED r2e_tests/test_1.py::TestDeriveView::test_secured_view_authz_policy_no_authn_policy\nPASSED r2e_tests/test_1.py::TestDeriveView::test_secured_view_raises_forbidden_no_name\nPASSED r2e_tests/test_1.py::TestDeriveView::test_secured_view_raises_forbidden_with_name\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_debug_authorization_authn_policy_no_authz_policy\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_debug_authorization_authz_policy_no_authn_policy\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_debug_authorization_no_authpol\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_debug_authorization_no_permission\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_predicates_all\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_predicates_checker\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_predicates_notall\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_view_mapper_config_specified\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_view_mapper_default_mapper_specified\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_view_mapper_view_specified\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_wrapper_viewname\nPASSED r2e_tests/test_1.py::TestDeriveView::test_with_wrapper_viewname_notfound\nPASSED r2e_tests/test_1.py::TestDerivationOrder::test_right_order_implicit\nPASSED r2e_tests/test_1.py::TestDerivationOrder::test_right_order_under_rendered_view\nPASSED r2e_tests/test_1.py::TestDerivationOrder::test_right_order_under_rendered_view_others\nPASSED r2e_tests/test_1.py::TestDerivationOrder::test_right_order_user_sorted\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_reserves_ingress\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_without_name\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_multi_derivers_ordered\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_add_single_deriver\nPASSED r2e_tests/test_1.py::TestAddDeriver::test_override_deriver\nPASSED r2e_tests/test_1.py::TestDeriverIntegration::test_unexpected_view_options\nPASSED r2e_tests/test_1.py::TestDeriverIntegration::test_view_options\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_object_event_subscriber\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_resource_url_default_resource_iface_means_Interface\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_resource_url_nodefault_resource_iface\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_response_adapter\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_response_adapter_dottednames\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_response_adapter_self\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_defaults\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_dottednames\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_iface_specified\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_predicate\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_with_default_type_predicates_False\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_with_default_type_predicates_True\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_with_specific_type_and_predicates_False\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_subscriber_with_specific_type_and_predicates_True\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_traverser_default_iface_means_Interface\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_traverser_introspectables\nPASSED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_traverser_nondefault_iface\nPASSED r2e_tests/test_config/test_adapters.py::Test_eventonly::test_defaults\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test__override_already_registered\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test__override_not_yet_registered\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_absdirectory\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_absfile\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_file\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_absdirectory\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_absfile\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_directory\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_missing_abspath\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_package\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_package_with_absdirectory\nPASSED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_samename\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_filename_override_returns_value\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_stream_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_stream_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_stream_override_returns_value\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_string_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_string_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_string_override_returns_value\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_has_resource_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_has_resource_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_has_resource_override_returns_True\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_isdir_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_isdir_override_returns_False\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_isdir_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_listdir_no_overrides\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_listdir_override_returns_None\nPASSED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_resource_listdir_override_returns_values\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_class_conforms_to_IPEP302Loader\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_class_conforms_to_IPackageOverrides\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_package_already_has_loader_of_different_type\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_package_already_has_loader_of_same_type\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_registers_loader_type\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_sets_loader\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_ctor_sets_local_state\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_filtered_sources\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_code_pkg_has___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_code_pkg_has_no___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_data_pkg_has___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_data_pkg_has_no___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_filename\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_filename_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_source_pkg_has___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_source_pkg_has_no___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_stream\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_stream_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_string\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_get_string_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_has_resource\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_has_resource_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_insert_directory\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_insert_emptystring\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_insert_file\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_instance_conforms_to_IPEP302Loader\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_instance_conforms_to_IPackageOverrides\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_is_package_pkg_has___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_is_package_pkg_has_no___loader__\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_isdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_isdir_false\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_isdir_true\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_listdir\nPASSED r2e_tests/test_config/test_assets.py::TestPackageOverrides::test_listdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_exists\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_exists_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_exists_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_filename_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_stream\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_stream_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_stream_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_string\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_string_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_string_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_isdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_isdir_false\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_isdir_true\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_listdir\nPASSED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_listdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_exists\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_exists_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_exists_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_filename\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_filename_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_filename_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_stream\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_stream_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_stream_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_string\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_string_file_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_get_string_with_prefix\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_isdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_isdir_false\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_isdir_true\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_listdir\nPASSED r2e_tests/test_config/test_assets.py::TestFSAssetSource::test_listdir_doesnt_exist\nPASSED r2e_tests/test_config/test_assets.py::TestDirectoryOverride::test_it_match\nPASSED r2e_tests/test_config/test_assets.py::TestDirectoryOverride::test_it_no_match\nPASSED r2e_tests/test_config/test_assets.py::TestFileOverride::test_it_match\nPASSED r2e_tests/test_config/test_assets.py::TestFileOverride::test_it_no_match\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_None_callable\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_None_callable_and_no_name\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_None_callable_conflict\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_callable\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_text_type_name\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_add_request_method_with_unnamed_callable\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_multiple_request_methods_conflict\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_request_factory\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_request_factory_dottedname\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_response_factory\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_response_factory_dottedname\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_root_factory\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_root_factory_as_None\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_root_factory_dottedname\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_session_factory\nPASSED r2e_tests/test_config/test_factories.py::TestFactoriesMixin::test_set_session_factory_dottedname\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_multiple_request_properties\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_multiple_request_properties_conflict\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_request_property_with_callable\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_request_property_with_property\nPASSED r2e_tests/test_config/test_factories.py::TestDeprecatedFactoriesMixinMethods::test_set_request_property_with_unnamed_callable\nPASSED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_missing_dir\nPASSED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_no_specs\nPASSED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_set_locale_negotiator\nPASSED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_set_locale_negotiator_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test___getattr__matches\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test___getattr__matches_no_action_wrap\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test___getattr__missing_when_directives_dont_exist\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test___getattr__missing_when_directives_exist\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_adds__lock\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_adds_clear_view_lookup_cache\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_has_listeners\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_notify\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_queryAdapterOrSelf\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test__fix_registry_registerSelfAdapter\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_absolute_asset_spec_already_absolute\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_absolute_asset_spec_notastring\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_absolute_asset_spec_relative\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_autocommit_with_introspectables\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_autocommit_with_introspectables_introspection_off\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_kw_is_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_kw_is_not_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_nonautocommit_with_config_info\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_nonautocommit_with_introspectables\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_branching_nonautocommit_without_config_info\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_action_nonautocommit_with_introspectables_introspection_off\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_autocommit_no_conflicts\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_begin\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_begin_with_request\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_commit_conflict_resolved_with_include\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_commit_conflict_resolved_with_two_includes_and_local\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_commit_conflict_simple\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_commit_conflict_with_two_includes\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_conflict_set_forbidden_view\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_conflict_set_notfound_view\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_alternate_renderers\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_authentication_policy\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_authorization_policy_only\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_default_permission\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_default_renderers\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_default_view_mapper\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_default_webob_response_adapter_registered\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_exceptionresponse_view_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_exceptionresponse_view_custom\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_httpexception_view_default\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_no_root_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_noreg_custom_settings\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_noreg_debug_logger_non_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_session_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_with_introspection\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_with_package_registry\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_with_root_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_end\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_hook_zca\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_dotted_name\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_missing_source_file\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_module_defaults_to_includeme\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_module_defaults_to_includeme_missing\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_nested_route_prefix\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_python_callable\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_with_route_prefix\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_introspector_decorator\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_make_wsgi_app\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_maybe_dotted_notstring_success\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_maybe_dotted_string_fail\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_maybe_dotted_string_success\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_dottedname_package\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_with_extra_kw\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_with_ignore\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_with_onerror\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_alternate_renderers\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_authentication_policy\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_authentication_policy_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_authorization_policy_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_authorization_policy_only\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_calls_fix_registry\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_custom_settings\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_debug_logger_name\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_debug_logger_non_None\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_default_permission\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_dottedname_root_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_explicit_notfound_trumps_iexceptionresponse\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_includes\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_includes_spaces\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_locale_negotiator\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_locale_negotiator_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_no_default_root_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_registers_default_exceptionresponse_views\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_registers_default_view_predicates\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_registers_default_webob_iresponse_adapter\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_request_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_request_factory_dottedname\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_response_factory\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_tweens\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_unhook_zca\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_with_package\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_with_package_module\nPASSED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_with_package_package\nPASSED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_directive_persists_across_configurator_creations\nPASSED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_extend_action_method_successful\nPASSED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_extend_same_name_doesnt_conflict\nPASSED r2e_tests/test_config/test_init.py::TestConfigurator__add_predicate::test_factory_as_object\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_simple\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_includepath\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_includepath_and_info\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_info\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_introspectables\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_action_with_order\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_dicts\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_error\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_tuples\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_with_introspectable_no_callable\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_execute_actions_with_introspectables\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_it\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_processSpec\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_reentrant_action\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_reentrant_action_error\nPASSED r2e_tests/test_config/test_init.py::TestActionState::test_reentrant_action_without_clear\nPASSED r2e_tests/test_config/test_init.py::Test_reentrant_action_functional::test_functional\nPASSED r2e_tests/test_config/test_init.py::Test_resolveConflicts::test_it_conflict\nPASSED r2e_tests/test_config/test_init.py::Test_resolveConflicts::test_it_success_dicts\nPASSED r2e_tests/test_config/test_init.py::Test_resolveConflicts::test_it_success_tuples\nPASSED r2e_tests/test_config/test_init.py::Test_resolveConflicts::test_it_with_actions_grouped_by_order\nPASSED r2e_tests/test_config/test_init.py::TestGlobalRegistriesIntegration::test_global_registries\nPASSED r2e_tests/test_config/test_init.py::TestGlobalRegistriesIntegration::test_global_registries_empty\nPASSED r2e_tests/test_config/test_predicates.py::TestXHRPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestXHRPredicate::test___call___true\nPASSED r2e_tests/test_config/test_predicates.py::TestXHRPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestXHRPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test___call___true_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test___call___true_single\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test_ctor_get_but_no_head\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestMethodPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test___call___true\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test_ctor_compilefail\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestPathInfoPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___false_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___true_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___true_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test___call___true_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_phash_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_phash_exists_equal_sign\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_phash_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_exists_equal_sign\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_multi_equal_sign\nPASSED r2e_tests/test_config/test_predicates.py::TestRequestParamPredicate::test_text_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test___call___matchdict_is_None\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test___call___true_multi\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test___call___true_single\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestMatchParamPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test___call___true\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test_text_func_has___text__\nPASSED r2e_tests/test_config/test_predicates.py::TestCustomPredicate::test_text_func_repr\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test___call__traverse_has_remainder_already\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test___call__traverse_matches\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test___call__traverse_matches_with_highorder_chars\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::TestTraversePredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_it_call_val_False\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_it_call_val_True\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_it_call_val_str\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::Test_CheckCSRFTokenPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___false\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___false_withregex\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___true_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___true_withregex\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test___call___true_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_phash_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_phash_withregex\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_phash_withval\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_text_exists\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_text_withregex\nPASSED r2e_tests/test_config/test_predicates.py::TestHeaderPredicate::test_text_withval\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_False\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_context_has_no_name\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_val_list_True\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_val_str_True\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_it_call_val_tuple_True\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::Test_PhysicalPathPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_it_call_authentication_policy_doesnt_provide_superset\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_it_call_authentication_policy_provides_superset\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_it_call_authentication_policy_provides_superset_implicit\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_it_call_no_authentication_policy\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_phash\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_text\nPASSED r2e_tests/test_config/test_predicates.py::Test_EffectivePrincipalsPredicate::test_text_noniter\nPASSED r2e_tests/test_config/test_rendering.py::TestRenderingConfiguratorMixin::test_add_default_renderers\nPASSED r2e_tests/test_config/test_rendering.py::TestRenderingConfiguratorMixin::test_add_renderer\nPASSED r2e_tests/test_config/test_rendering.py::TestRenderingConfiguratorMixin::test_add_renderer_dottedname_factory\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_defaults\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_discriminator\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_path_no_pattern\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_pattern_with_path\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_view_with_view_attr\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_view_with_view_context\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_view_with_view_permission\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_no_view_with_view_renderer\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_accept\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_custom_predicates\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_factory\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_factory_dottedname\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_header\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_path_info\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_path_info_highorder\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_path_info_regex\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_pregenerator\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_request_method\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_request_param\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_route_prefix\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_static\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_add_route_with_xhr\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_get_routes_mapper_already_registered\nPASSED r2e_tests/test_config/test_routes.py::RoutesConfiguratorMixinTests::test_get_routes_mapper_not_yet_registered\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_add_permission\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authentication_policy_no_authz_policy\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authentication_policy_no_authz_policy_autocommit\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authentication_policy_with_authz_policy\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authentication_policy_with_authz_policy_autocommit\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authorization_policy_no_authn_policy\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authorization_policy_no_authn_policy_autocommit\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authorization_policy_with_authn_policy\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_authorization_policy_with_authn_policy_autocommit\nPASSED r2e_tests/test_config/test_security.py::ConfiguratorSecurityMethodsTests::test_set_default_permission\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test__set_settings_as_None\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test__set_settings_as_dictwithvalues\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_add_settings_settings_None\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_add_settings_settings_already_registered\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_add_settings_settings_not_yet_registered\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_get_settings_nosettings\nPASSED r2e_tests/test_config/test_settings.py::TestSettingsConfiguratorMixin::test_get_settings_withsettings\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_all\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_authorization\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_notfound\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_routematch\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_debug_templates\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_default_locale_name\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_getattr_fail\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_getattr_raises_attribute_error\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_getattr_success\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_noargs\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_originals_kept\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_prevent_cachebust\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_prevent_http_cache\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_reload_all\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_reload_assets\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_reload_resources\nPASSED r2e_tests/test_config/test_settings.py::TestSettings::test_reload_templates\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_renderer\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_renderer_explicitrenderer\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_renderer_twice\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_subscriber_defaults\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_subscriber_dottedname\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_subscriber_multiple\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_subscriber_single\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_add_template\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_resources\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_securitypolicy\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_securitypolicy_forget_result\nPASSED r2e_tests/test_config/test_testing.py::TestingConfiguratorMixinTests::test_testing_securitypolicy_remember_result\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_dottedname\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_instance\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_name_ingress\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_name_main\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_over_ingress\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_over_ingress_iterable\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_under_main\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_under_main_iterable\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tween_unsuitable\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_conflict\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_names_distinct\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_names_with_over_nonstringoriter\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_names_with_under_nonstringoriter\nPASSED r2e_tests/test_config/test_tweens.py::TestTweensConfiguratorMixin::test_add_tweens_names_with_underover\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test___call___explicit\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test___call___implicit\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_add_explicit\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_add_implicit\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_1\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_2\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_3\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_4\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_5\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_conflict_direct\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_conflict_indirect\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_over_and_under_partials\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_over_partial\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_over_partial_with_fallback\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_under_partial\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_missing_under_partial_with_fallback\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_with_missing_fallbacks\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_with_multiple_matching_fallbacks\nPASSED r2e_tests/test_config/test_tweens.py::TestTweens::test_implicit_ordering_with_partial_fallbacks\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_custom_predicates_can_affect_traversal\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_different_custom_predicates_with_same_hash\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_match_param_from_dict\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_match_param_from_dict_fails\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_match_param_from_string\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_match_param_from_string_fails\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_notted\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_ordering_importance_and_number\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_ordering_importance_of_predicates\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_ordering_number_of_predicates\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_ordering_xhr_and_request_method_trump_only_containment\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_predicate_text_is_correct\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_request_method_ordering_hashes_same\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_request_method_sequence\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_traverse_has_remainder_already\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_traverse_matches\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_traverse_matches_with_highorder_chars\nPASSED r2e_tests/test_config/test_util.py::TestPredicateList::test_unknown_predicate\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_annotations\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_defaultargs_firstname_not_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_defaultargs_firstname_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_noargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_onearg_named_somethingelse\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_toomanyargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_with_attr_false\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_function_with_attr_true\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_defaultargs_firstname_not_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_defaultargs_firstname_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_defaultargs_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_defaultargs_onearg_named_somethingelse\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_nocall\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_instance_toomanyargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_method_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_defaultargs_firstname_not_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_defaultargs_firstname_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_firstname_request_with_secondname\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_noargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_newstyle_class_init_onearg_named_somethingelse\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_defaultargs_firstname_not_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_defaultargs_firstname_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_noargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_onearg_named_somethingelse\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_init_toomanyargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_oldstyle_class_no_init\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_requestonly_newstyle_class_init_onearg_named_request\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_requestonly_newstyle_class_init_toomanyargs\nPASSED r2e_tests/test_config/test_util.py::Test_takes_one_arg::test_requestonly_newstyle_class_no_init\nPASSED r2e_tests/test_config/test_util.py::TestNotted::test_it_with_phash_val\nPASSED r2e_tests/test_config/test_util.py::TestNotted::test_it_without_phash_val\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_allows_other_predicates\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_context\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_for_\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_http_cache\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_disallows_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_no_view_argument\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_with_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_forbidden_view_with_view_defaults\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_allows_other_predicates\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_append_slash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_append_slash_custom_response\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_context\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_for_\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_http_cache\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_disallows_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_no_view_argument\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_with_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_notfound_view_with_view_defaults\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_static_view_absolute\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_static_view_here_no_utility_registered\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_static_view_package_relative\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_instance\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_instance_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_instancemethod\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_instancemethod_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_oldstyle_class\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_as_oldstyle_class_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_class_method_no_attr\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_context_as_class\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_context_as_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_context_as_iface\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_context_trumps_for\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_custom_more_preds_first_bests_fewer_preds_last\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_custom_predicate_bests_standard_predicate\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_default_phash_overrides_default_phash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_default_phash_overrides_no_phash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_default_phash_overrides_default_phash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_default_phash_overrides_no_phash\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_multiview_replaces_existing_securedview\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_multiview_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_multiview_replaces_multiview\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_mulview_replaces_existing_view_with___accept__\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_same_phash_overrides_existing_single_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exc_with_accept_multiview_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_exception_register_secured_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_for__as_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_for_as_class\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_for_as_iface\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_mixed_case_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview___discriminator__\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_call_ordering\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_context_superclass_then_subclass\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_exception_superclass_then_subclass\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_replaces_existing_securedview\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_replaces_existing_view_with___accept__\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_multiview_replaces_multiview\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_register_secured_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_same_phash_overrides_existing_single_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_same_predicates\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_view_callable_None_no_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_view_callable_None_with_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_view_callable_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_accept_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_accept_multiview_replaces_existing_view\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_accept_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_containment_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_containment_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_containment_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_custom_predicates_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_custom_predicates_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_decorator\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_decorator_tuple\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_default_permission_no_explicit_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_default_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_function_callable\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_function_callable_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_badregex\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_noval_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_noval_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_val_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_val_missing\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_header_val_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_http_cache\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_mapper\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_name_unicode\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_no_default_permission_no_explicit_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_nonexistant_route_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_path_info_badregex\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_path_info_match\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_path_info_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_permission\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_get_implies_head\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_sequence_conflict\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_sequence_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_sequence_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_method_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_param_noval_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_param_noval_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_param_val_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_param_val_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_type\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_type_and_route_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_type_as_iface\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_request_type_as_noniface\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_route_name\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_route_name_exception\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_tmpl_renderer_factory_introspector_missing\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_tmpl_renderer_factory_no_renderer_factory\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_tmpl_renderer_factory_with_renderer_factory\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_config_and_view_defaults_conflicts\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_config_and_view_defaults_doesnt_conflict\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_defaults\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_defaults_viewname_is_dottedname_kwarg\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_view_defaults_viewname_is_dottedname_nonkwarg\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_xhr_false\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_xhr_true\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_wrapped_view_is_decorated\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_views_with_accept_multiview_replaces_existing\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_derive_view_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_derive_view_function\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_derive_view_with_default_renderer_no_explicit_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_derive_view_with_default_renderer_with_explicit_renderer\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_set_view_mapper\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_set_view_mapper_dottedname\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_view_with_most_specific_predicate\nPASSED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_view_with_most_specific_predicate_with_mismatch\nPASSED r2e_tests/test_config/test_views.py::Test_requestonly::test_defaults\nPASSED r2e_tests/test_config/test_views.py::Test_requestonly::test_otherattr\nPASSED r2e_tests/test_config/test_views.py::Test_isexception::test_is_IException\nPASSED r2e_tests/test_config/test_views.py::Test_isexception::test_is_IException_subinterface\nPASSED r2e_tests/test_config/test_views.py::Test_isexception::test_is_exception_class\nPASSED r2e_tests/test_config/test_views.py::Test_isexception::test_is_exception_instance\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call__\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call__intermediate_not_found\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call__raise_not_found_isnt_interpreted_as_pred_mismatch\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call_permissive_has_call_permissive\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test___call_permissive_has_no_call_permissive\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test__call__not_found\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test__call__with_accept_match\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test__call__with_accept_miss\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test__call_permissive__not_found\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_add\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_add_with_phash\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_add_with_phash_override_accept\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_add_with_phash_override_accept2\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_class_implements_ISecuredView\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_get_views\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_get_views_best_match_returns_None\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_get_views_no_self_accepts\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_get_views_request_has_no_accept\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_instance_implements_ISecuredView\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_match_not_found\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_match_predicate_fails\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_match_predicate_succeeds\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_multiple_with_functions_as_views\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_permitted\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_permitted_no_match_with__permitted__\nPASSED r2e_tests/test_config/test_views.py::TestMultiView::test_permitted_no_views\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test__view_as_function_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_function_context_and_request\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_function_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_function_requestonly_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_instance_context_and_request\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_instance_context_and_request_and_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_instance_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_instance_requestonly_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_newstyle_class_context_and_request\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_newstyle_class_context_and_request_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_newstyle_class_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_newstyle_class_requestonly_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_oldstyle_class_context_and_request\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_oldstyle_class_context_and_request_with_attr\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_oldstyle_class_requestonly\nPASSED r2e_tests/test_config/test_views.py::TestDefaultViewMapper::test_view_as_oldstyle_class_requestonly_with_attr\nPASSED r2e_tests/test_config/test_views.py::Test_preserve_view_attrs::test_it_different\nPASSED r2e_tests/test_config/test_views.py::Test_preserve_view_attrs::test_it_different_with_existing_original_view\nPASSED r2e_tests/test_config/test_views.py::Test_preserve_view_attrs::test_it_same\nPASSED r2e_tests/test_config/test_views.py::Test_preserve_view_attrs::test_it_view_is_None\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_already_exists\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebust_prevented\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster_abspath\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster_for_more_specific_path\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster_overwrite\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_cachebuster_overwrite_explicit\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_package_root\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_url_noendslash\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_url_noscheme\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_url_withendslash\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_context\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_for_\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_permission\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_renderer\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_add_viewname_with_route_prefix\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_missing\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_quoting\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_registration_miss\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_route_url\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_slash_in_name1\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_slash_in_name2\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_cachebust\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_cachebust_abspath\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_cachebust_nomatch\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_quoted_remote\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_unquoted_local\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_with_custom_anchor\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_with_custom_query\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_verifyClass\nPASSED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_verifyObject\nPASSED r2e_tests/test_config/test_views.py::Test_view_description::test_with_text\nPASSED r2e_tests/test_scripts/test_common.py::Test_logging_file_config::test_it\nPASSED r2e_tests/test_scripts/test_common.py::TestParseVars::test_parse_vars_bad\nPASSED r2e_tests/test_scripts/test_common.py::TestParseVars::test_parse_vars_good\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_confirm_override_conflicting_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_force_override_conflicting_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_force_override_site_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_known_scaffold_absolute_path\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_known_scaffold_multiple_rendered\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_known_scaffold_single_rendered\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_known_scaffold_with_path_as_project_target_rendered\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_no_project_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_run_no_scaffold_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_run_no_scaffold_no_args\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_run_show_scaffolds_exist\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_run_show_scaffolds_none_exist\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_dev_pyramid_long_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_dev_pyramid_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_hyphen_in_project_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_prod_pyramid_long_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_prod_pyramid_unparsable_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_scaffold_with_prod_pyramid_version\nPASSED r2e_tests/test_scripts/test_pcreate.py::TestPCreateCommand::test_unknown_scaffold_name\nPASSED r2e_tests/test_scripts/test_pcreate.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_pdistreport.py::TestPDistReportCommand::test_no_dists\nPASSED r2e_tests/test_scripts/test_pdistreport.py::TestPDistReportCommand::test_with_dists\nPASSED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_has_bad_config_header\nPASSED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_configures_logging\nPASSED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_not_enough_args\nPASSED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_response_has_no_charset\nPASSED r2e_tests/test_scripts/test_prequest.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test__get_mapper\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_bad_args\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_bad_format\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_good_args\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_good_format\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_no_mapper\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_no_routes\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_as_wsgiapp\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_no_view\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_with_no_slash_prefix\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_multiview_registered\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_no_route_registered\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_no_views_registered\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_one_view_registered_with_factory\nPASSED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_static_routes_included_in_list\nPASSED r2e_tests/test_scripts/test_proutes.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_get_options_no_command\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_get_options_with_command\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_parse_vars_bad\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_parse_vars_good\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_record_pid_not_verbose\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_record_pid_verbose\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_current_pid_is_not_pid_in_file\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_current_pid_is_not_written_pid\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_file_not_verbose\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_file_stale_pid_write_exception\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_file_unlink_exception\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_file_verbose\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_no_pid_file\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_remove_pid_not_a_number\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_run_no_args\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_run_stop_daemon_bad_pid_file\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_run_stop_daemon_invalid_pid_in_file\nPASSED r2e_tests/test_scripts/test_pserve.py::TestPServeCommand::test_run_stop_daemon_no_such_pid_file\nPASSED r2e_tests/test_scripts/test_pserve.py::Test_read_pidfile::test_read_pidfile\nPASSED r2e_tests/test_scripts/test_pserve.py::Test_read_pidfile::test_read_pidfile_no_pid_file\nPASSED r2e_tests/test_scripts/test_pserve.py::Test_read_pidfile::test_read_pidfile_not_a_number\nPASSED r2e_tests/test_scripts/test_pserve.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_pserve.py::TestLazyWriter::test_flush\nPASSED r2e_tests/test_scripts/test_pserve.py::TestLazyWriter::test_open\nPASSED r2e_tests/test_scripts/test_pserve.py::TestLazyWriter::test_write\nPASSED r2e_tests/test_scripts/test_pserve.py::TestLazyWriter::test_writeline\nPASSED r2e_tests/test_scripts/test_pserve.py::Test__methodwrapper::test___call__fail\nPASSED r2e_tests/test_scripts/test_pserve.py::Test__methodwrapper::test___call__succeed\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_custom_section_override\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_default_shell_option\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_errors_with_unknown_shell\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_check_variable_override_order\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_custom_items\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_default_shell\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_ipython\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_pythonstartup\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_loads_setup_from_options\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_command_setup\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_list_shells\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_shell_entry_points\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_shell_ordering\nPASSED r2e_tests/test_scripts/test_pshell.py::TestPShellCommand::test_shell_override\nPASSED r2e_tests/test_scripts/test_pshell.py::Test_python_shell_runner::test_it\nPASSED r2e_tests/test_scripts/test_pshell.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_ptweens.py::TestPTweensCommand::test__get_tweens\nPASSED r2e_tests/test_scripts/test_ptweens.py::TestPTweensCommand::test_command_implicit_and_explicit_tweens\nPASSED r2e_tests/test_scripts/test_ptweens.py::TestPTweensCommand::test_command_implicit_tweens_only\nPASSED r2e_tests/test_scripts/test_ptweens.py::TestPTweensCommand::test_command_no_tweens\nPASSED r2e_tests/test_scripts/test_ptweens.py::Test_main::test_it\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_multi_routes_all_match\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_multi_routes_none_match\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_multi_routes_some_match\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_no_match\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_no_match_multiview_registered\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_route_multiview\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_route_multiview_no_view_registered\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_route_no_multiview\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_traversal\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test__find_view_traversal_multiview\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_multi_view_nested\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_multiview\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_multiview_with_permission\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_multiview_with_predicates\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_not_found\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_not_found_url_starts_without_slash\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_route\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_route_with_route_predicates\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_traversal\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_traversal_with_permission\nPASSED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_traversal_with_predicates\nPASSED r2e_tests/test_scripts/test_pviews.py::Test_main::test_it\nFAILED r2e_tests/test_1.py::TestDeriveView::test_as_instance_requestonly - As...\nFAILED r2e_tests/test_1.py::TestDeriveView::test_function_returns_non_adaptable\nFAILED r2e_tests/test_1.py::TestDeriveView::test_function_returns_non_adaptable_dict\nFAILED r2e_tests/test_1.py::TestDeriveView::test_instance_returns_non_adaptable\nFAILED r2e_tests/test_1.py::TestDeriveView::test_requestonly_default_method_returns_non_adaptable\nFAILED r2e_tests/test_1.py::TestDeriveView::test_requestonly_nondefault_method_returns_non_adaptable\nFAILED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_enforces_ingress_is_first\nFAILED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_enforces_mapped_view_is_last\nFAILED r2e_tests/test_1.py::TestAddDeriver::test_add_deriver_enforces_view_is_last\nFAILED r2e_tests/test_1.py::TestAddDeriver::test_override_mapped_view - Impor...\nFAILED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_resource_url_adapter_dotted_names\nFAILED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_resource_url_adapter_introspectables\nFAILED r2e_tests/test_config/test_adapters.py::AdaptersConfiguratorMixinTests::test_add_traverser_dotted_names\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_directory\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_directory_with_package\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_file_with_file\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_package_with_directory\nFAILED r2e_tests/test_config/test_assets.py::TestAssetsConfiguratorMixin::test_override_asset_package_with_package\nFAILED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_filename_no_overrides\nFAILED r2e_tests/test_config/test_assets.py::TestOverrideProvider::test_get_resource_filename_override_returns_None\nFAILED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_filename\nFAILED r2e_tests/test_config/test_assets.py::TestPackageAssetSource::test_get_filename_with_prefix\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_abspath\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_asset_spec\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_asset_spec_existing_translation_dirs\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_multiple_specs\nFAILED r2e_tests/test_config/test_i18n.py::TestI18NConfiguratorMixin::test_add_translation_dirs_multiple_specs_multiple_calls\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_no_registry\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_ctor_noreg_debug_logger_None_default\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_include_constant_root_package\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_scan_integration_conflict\nFAILED r2e_tests/test_config/test_init.py::ConfiguratorTests::test_setup_registry_debug_logger_None_default\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_add_directive_with_custom_callable\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_add_directive_with_partial\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_extend_with_dotted_name\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator_add_directive::test_extend_with_python_callable\nFAILED r2e_tests/test_config/test_init.py::TestConfigurator__add_predicate::test_factory_as_dotted_name\nFAILED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_static_view_package_here_relative\nFAILED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_template_renderer\nFAILED r2e_tests/test_config/test_views.py::TestViewsConfigurationMixin::test_add_view_with_template_renderer_no_callable\nFAILED r2e_tests/test_config/test_views.py::TestStaticURLInfo::test_generate_url_cachebust_with_overrides\nFAILED r2e_tests/test_config/test_views.py::Test_view_description::test_without_text\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_display_headers\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_has_content_type_header_var\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_has_good_header_var\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_has_multiple_header_vars\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_get\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_options\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_patch\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_post\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_propfind\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_method_put\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_path_doesnt_start_with_slash\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_two_args\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_w_basic_auth\nFAILED r2e_tests/test_scripts/test_prequest.py::TestPRequestCommand::test_command_with_query_string\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_config_format_ini_commas\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_config_format_ini_newlines\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_config_format_ini_spaces\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_one_route_all_methods_view_only_post\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_one_route_only_post_view_all_methods\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_one_route_only_post_view_post_and_get\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_one_route_with_long_name_one_view_registered\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_is_get_view_request_method_not_post\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_request_method_mismatch\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_route_static_views\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_single_route_one_view_registered\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_view_glob\nFAILED r2e_tests/test_scripts/test_proutes.py::TestPRoutesCommand::test_view_request_method_not_post\nFAILED r2e_tests/test_scripts/test_pviews.py::TestPViewsCommand::test_views_command_single_view_function_traversal\n======================== 70 failed, 893 passed in 4.76s ========================\n",
    "old_commit_res_stderr": ""
}
docs/api/viewderivers.rst docs/narr/hooks.rst pyramid/config/views.py pyramid/tests/test_viewderivers.py pyramid/viewderivers.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
### ImportError: Cannot Import 'VIEW' from 'pyramid.viewderivers'

#### Description
After updating the constraints for view derivers, attempting to import the `VIEW` constant from `pyramid.viewderivers` results in an `ImportError`. This prevents certain tests from running successfully and disrupts the configuration of view derivers.

#### Example Code
```python
from pyramid.viewderivers import VIEW

def test_add_deriver_enforces_view_is_last():
    from pyramid.exceptions import ConfigurationError

    def deriv1(view, info): pass
    try:
        config.add_view_deriver(deriv1, under=VIEW)
    except ConfigurationError as ex:
        assert 'cannot be under VIEW' in ex.args[0]
    else:
        raise AssertionError
```

#### Expected Behavior
The `VIEW` constant should be successfully imported from `pyramid.viewderivers`, allowing tests and configurations that rely on it to function correctly.

#### Actual Behavior
An `ImportError` is raised:
```
ImportError: cannot import name 'VIEW' from 'pyramid.viewderivers' (/path/to/pyramid/viewderivers.py)
```

This error indicates that the `VIEW` constant is either not defined or not properly exposed in the `pyramid.viewderivers` module after the recent commit.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### pyramid/viewderivers.py
import inspect

from zope.interface import (
    implementer,
    provider,
    )

from pyramid.security import NO_PERMISSION_REQUIRED
from pyramid.response import Response

from pyramid.interfaces import (
    IAuthenticationPolicy,
    IAuthorizationPolicy,
    IDebugLogger,
    IResponse,
    IViewMapper,
    IViewMapperFactory,
    )

from pyramid.compat import (
    is_bound_method,
    is_unbound_method,
    )

from pyramid.config.util import (
    DEFAULT_PHASH,
    MAX_ORDER,
    takes_one_arg,
    )

from pyramid.exceptions import (
    ConfigurationError,
    PredicateMismatch,
    )
from pyramid.httpexceptions import HTTPForbidden
from pyramid.util import object_description
from pyramid.view import render_view_to_response
from pyramid import renderers


def view_description(view):
    try:
        return view.__text__
    except AttributeError:
        # custom view mappers might not add __text__
        return object_description(view)

def requestonly(view, attr=None):
    return takes_one_arg(view, attr=attr, argname='request')

@implementer(IViewMapper)
@provider(IViewMapperFactory)
class DefaultViewMapper(object):
    def __init__(self, **kw):
        self.attr = kw.get('attr')

    def __call__(self, view):
        if is_unbound_method(view) and self.attr is None:
            raise ConfigurationError((
                'Unbound method calls are not supported, please set the class '
                'as your `view` and the method as your `attr`'
            ))

        if inspect.isclass(view):
            view = self.map_class(view)
        else:
            view = self.map_nonclass(view)
        return view

    def map_class(self, view):
        ronly = requestonly(view, self.attr)
        if ronly:
            mapped_view = self.map_class_requestonly(view)
        else:
            mapped_view = self.map_class_native(view)
        mapped_view.__text__ = 'method %s of %s' % (
            self.attr or '__call__', object_description(view))
        return mapped_view

    def map_nonclass(self, view):
        # We do more work here than appears necessary to avoid wrapping the
        # view unless it actually requires wrapping (to avoid function call
        # overhead).
        mapped_view = view
        ronly = requestonly(view, self.attr)
        if ronly:
            mapped_view = self.map_nonclass_requestonly(view)
        elif self.attr:
            mapped_view = self.map_nonclass_attr(view)
        if inspect.isroutine(mapped_view):
            # This branch will be true if the view is a function or a method.
            # We potentially mutate an unwrapped object here if it's a
            # function.  We do this to avoid function call overhead of
            # injecting another wrapper.  However, we must wrap if the
            # function is a bound method because we can't set attributes on a
            # bound method.
            if is_bound_method(view):
                _mapped_view = mapped_view
                def mapped_view(context, request):
                    return _mapped_view(context, request)
            if self.attr is not None:
                mapped_view.__text__ = 'attr %s of %s' % (
                    self.attr, object_description(view))
            else:
                mapped_view.__text__ = object_description(view)
        return mapped_view

    def map_class_requestonly(self, view):
        # its a class that has an __init__ which only accepts request
        attr = self.attr
        def _class_requestonly_view(context, request):
            inst = view(request)
            request.__view__ = inst
            if attr is None:
                response = inst()
            else:
                response = getattr(inst, attr)()
            return response
        return _class_requestonly_view

    def map_class_native(self, view):
        # its a class that has an __init__ which accepts both context and
        # request
        attr = self.attr
        def _class_view(context, request):
            inst = view(context, request)
            request.__view__ = inst
            if attr is None:
                response = inst()
            else:
                response = getattr(inst, attr)()
            return response
        return _class_view

    def map_nonclass_requestonly(self, view):
        # its a function that has a __call__ which accepts only a single
        # request argument
        attr = self.attr
        def _requestonly_view(context, request):
            if attr is None:
                response = view(request)
            else:
                response = getattr(view, attr)(request)
            return response
        return _requestonly_view

    def map_nonclass_attr(self, view):
        # its a function that has a __call__ which accepts both context and
        # request, but still has an attr
        def _attr_view(context, request):
            response = getattr(view, self.attr)(context, request)
            return response
        return _attr_view


def wraps_view(wrapper):
    def inner(view, info):
        wrapper_view = wrapper(view, info)
        return preserve_view_attrs(view, wrapper_view)
    return inner

def preserve_view_attrs(view, wrapper):
    if view is None:
        return wrapper

    if wrapper is view:
        return view

    original_view = getattr(view, '__original_view__', None)

    if original_view is None:
        original_view = view

    wrapper.__wraps__ = view
    wrapper.__original_view__ = original_view
    wrapper.__module__ = view.__module__
    wrapper.__doc__ = view.__doc__

    try:
        wrapper.__name__ = view.__name__
    except AttributeError:
        wrapper.__name__ = repr(view)

    # attrs that may not exist on "view", but, if so, must be attached to
    # "wrapped view"
    for attr in ('__permitted__', '__call_permissive__', '__permission__',
                 '__predicated__', '__predicates__', '__accept__',
                 '__order__', '__text__'):
        try:
            setattr(wrapper, attr, getattr(view, attr))
        except AttributeError:
            pass

    return wrapper

def mapped_view(view, info):
    mapper = info.options.get('mapper')
    if mapper is None:
        mapper = getattr(view, '__view_mapper__', None)
        if mapper is None:
            mapper = info.registry.queryUtility(IViewMapperFactory)
            if mapper is None:
                mapper = DefaultViewMapper

    mapped_view = mapper(**info.options)(view)
    return mapped_view

mapped_view.options = ('mapper', 'attr')

def owrapped_view(view, info):
    wrapper_viewname = info.options.get('wrapper')
    viewname = info.options.get('name')
    if not wrapper_viewname:
        return view
    def _owrapped_view(context, request):
        response = view(context, request)
        request.wrapped_response = response
        request.wrapped_body = response.body
        request.wrapped_view = view
        wrapped_response = render_view_to_response(context, request,
                                                   wrapper_viewname)
        if wrapped_response is None:
            raise ValueError(
                'No wrapper view named %r found when executing view '
                'named %r' % (wrapper_viewname, viewname))
        return wrapped_response
    return _owrapped_view

owrapped_view.options = ('name', 'wrapper')

def http_cached_view(view, info):
    if info.settings.get('prevent_http_cache', False):
        return view

    seconds = info.options.get('http_cache')

    if seconds is None:
        return view

    options = {}

    if isinstance(seconds, (tuple, list)):
        try:
            seconds, options = seconds
        except ValueError:
            raise ConfigurationError(
                'If http_cache parameter is a tuple or list, it must be '
                'in the form (seconds, options); not %s' % (seconds,))

    def wrapper(context, request):
        response = view(context, request)
        prevent_caching = getattr(response.cache_control, 'prevent_auto',
                                  False)
        if not prevent_caching:
            response.cache_expires(seconds, **options)
        return response

    return wrapper

http_cached_view.options = ('http_cache',)

def secured_view(view, info):
    for wrapper in (_secured_view, _authdebug_view):
        view = wraps_view(wrapper)(view, info)
    return view

secured_view.options = ('permission',)

def _secured_view(view, info):
    permission = info.options.get('permission')
    if permission == NO_PERMISSION_REQUIRED:
        # allow views registered within configurations that have a
        # default permission to explicitly override the default
        # permission, replacing it with no permission at all
        permission = None

    wrapped_view = view
    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)
    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)

    if authn_policy and authz_policy and (permission is not None):
        def _permitted(context, request):
            principals = authn_policy.effective_principals(request)
            return authz_policy.permits(context, principals, permission)
        def _secured_view(context, request):
            result = _permitted(context, request)
            if result:
                return view(context, request)
            view_name = getattr(view, '__name__', view)
            msg = getattr(
                request, 'authdebug_message',
                'Unauthorized: %s failed permission check' % view_name)
            raise HTTPForbidden(msg, result=result)
        _secured_view.__call_permissive__ = view
        _secured_view.__permitted__ = _permitted
        _secured_view.__permission__ = permission
        wrapped_view = _secured_view

    return wrapped_view

def _authdebug_view(view, info):
    wrapped_view = view
    settings = info.settings
    permission = info.options.get('permission')
    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)
    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)
    logger = info.registry.queryUtility(IDebugLogger)
    if settings and settings.get('debug_authorization', False):
        def _authdebug_view(context, request):
            view_name = getattr(request, 'view_name', None)

            if authn_policy and authz_policy:
                if permission is NO_PERMISSION_REQUIRED:
                    msg = 'Allowed (NO_PERMISSION_REQUIRED)'
                elif permission is None:
                    msg = 'Allowed (no permission registered)'
                else:
                    principals = authn_policy.effective_principals(request)
                    msg = str(authz_policy.permits(
                        context, principals, permission))
            else:
                msg = 'Allowed (no authorization policy in use)'

            view_name = getattr(request, 'view_name', None)
            url = getattr(request, 'url', None)
            msg = ('debug_authorization of url %s (view name %r against '
                   'context %r): %s' % (url, view_name, context, msg))
            if logger:
                logger.debug(msg)
            if request is not None:
                request.authdebug_message = msg
            return view(context, request)

        wrapped_view = _authdebug_view

    return wrapped_view

def predicated_view(view, info):
    preds = info.predicates
    if not preds:
        return view
    def predicate_wrapper(context, request):
        for predicate in preds:
            if not predicate(context, request):
                view_name = getattr(view, '__name__', view)
                raise PredicateMismatch(
                    'predicate mismatch for view %s (%s)' % (
                        view_name, predicate.text()))
        return view(context, request)
    def checker(context, request):
        return all((predicate(context, request) for predicate in
                    preds))
    predicate_wrapper.__predicated__ = checker
    predicate_wrapper.__predicates__ = preds
    return predicate_wrapper

def attr_wrapped_view(view, info):
    accept, order, phash = (info.options.get('accept', None),
                            getattr(info, 'order', MAX_ORDER),
                            getattr(info, 'phash', DEFAULT_PHASH))
    # this is a little silly but we don't want to decorate the original
    # function with attributes that indicate accept, order, and phash,
    # so we use a wrapper
    if (
        (accept is None) and
        (order == MAX_ORDER) and
        (phash == DEFAULT_PHASH)
    ):
        return view # defaults
    def attr_view(context, request):
        return view(context, request)
    attr_view.__accept__ = accept
    attr_view.__order__ = order
    attr_view.__phash__ = phash
    attr_view.__view_attr__ = info.options.get('attr')
    attr_view.__permission__ = info.options.get('permission')
    return attr_view

attr_wrapped_view.options = ('accept', 'attr', 'permission')

def rendered_view(view, info):
    # one way or another this wrapper must produce a Response (unless
    # the renderer is a NullRendererHelper)
    renderer = info.options.get('renderer')
    if renderer is None:
        # register a default renderer if you want super-dynamic
        # rendering.  registering a default renderer will also allow
        # override_renderer to work if a renderer is left unspecified for
        # a view registration.
        def viewresult_to_response(context, request):
            result = view(context, request)
            if result.__class__ is Response: # common case
                response = result
            else:
                response = info.registry.queryAdapterOrSelf(result, IResponse)
                if response is None:
                    if result is None:
                        append = (' You may have forgotten to return a value '
                                  'from the view callable.')
                    elif isinstance(result, dict):
                        append = (' You may have forgotten to define a '
                                  'renderer in the view configuration.')
                    else:
                        append = ''

                    msg = ('Could not convert return value of the view '
                           'callable %s into a response object. '
                           'The value returned was %r.' + append)

                    raise ValueError(msg % (view_description(view), result))

            return response

        return viewresult_to_response

    if renderer is renderers.null_renderer:
        return view

    def rendered_view(context, request):
        result = view(context, request)
        if result.__class__ is Response: # potential common case
            response = result
        else:
            # this must adapt, it can't do a simple interface check
            # (avoid trying to render webob responses)
            response = info.registry.queryAdapterOrSelf(result, IResponse)
            if response is None:
                attrs = getattr(request, '__dict__', {})
                if 'override_renderer' in attrs:
                    # renderer overridden by newrequest event or other
                    renderer_name = attrs.pop('override_renderer')
                    view_renderer = renderers.RendererHelper(
                        name=renderer_name,
                        package=info.package,
                        registry=info.registry)
                else:
                    view_renderer = renderer.clone()
                if '__view__' in attrs:
                    view_inst = attrs.pop('__view__')
                else:
                    view_inst = getattr(view, '__original_view__', view)
                response = view_renderer.render_view(
                    request, result, view_inst, context)
        return response

    return rendered_view

rendered_view.options = ('renderer',)

def decorated_view(view, info):
    decorator = info.options.get('decorator')
    if decorator is None:
        return view
    return decorator(view)

decorated_view.options = ('decorator',)

MAPPED_VIEW = 'mapped_view'
INGRESS = 'INGRESS'


### pyramid/config/views.py
import inspect
import posixpath
import operator
import os
import warnings

from zope.interface import (
    Interface,
    implementedBy,
    implementer,
    )

from zope.interface.interfaces import IInterface

from pyramid.interfaces import (
    IDefaultPermission,
    IException,
    IExceptionViewClassifier,
    IMultiView,
    IPackageOverrides,
    IRendererFactory,
    IRequest,
    IResponse,
    IRouteRequest,
    ISecuredView,
    IStaticURLInfo,
    IView,
    IViewClassifier,
    IViewDerivers,
    IViewDeriverInfo,
    IViewMapperFactory,
    PHASE1_CONFIG,
    )

from pyramid import renderers

from pyramid.asset import resolve_asset_spec
from pyramid.compat import (
    string_types,
    urlparse,
    url_quote,
    WIN,
    is_nonstr_iter,
    )

from pyramid.decorator import reify

from pyramid.exceptions import (
    ConfigurationError,
    PredicateMismatch,
    )

from pyramid.httpexceptions import (
    HTTPForbidden,
    HTTPNotFound,
    default_exceptionresponse_view,
    )

from pyramid.registry import (
    predvalseq,
    Deferred,
    )

from pyramid.security import NO_PERMISSION_REQUIRED
from pyramid.static import static_view

from pyramid.url import parse_url_overrides

from pyramid.view import AppendSlashNotFoundViewFactory

import pyramid.util
from pyramid.util import (
    viewdefaults,
    action_method,
    TopologicalSorter,
    )

import pyramid.config.predicates
import pyramid.viewderivers

from pyramid.viewderivers import (
    INGRESS,
    MAPPED_VIEW,
    preserve_view_attrs,
    view_description,
    requestonly,
    DefaultViewMapper,
    wraps_view,
)

from pyramid.config.util import (
    DEFAULT_PHASH,
    MAX_ORDER,
    as_sorted_tuple,
    )

urljoin = urlparse.urljoin
url_parse = urlparse.urlparse

DefaultViewMapper = DefaultViewMapper # bw-compat
preserve_view_attrs = preserve_view_attrs # bw-compat
requestonly = requestonly # bw-compat
view_description = view_description # bw-compat

@implementer(IMultiView)
class MultiView(object):

    def __init__(self, name):
        self.name = name
        self.media_views = {}
        self.views = []
        self.accepts = []

    def __discriminator__(self, context, request):
        # used by introspection systems like so:
        # view = adapters.lookup(....)
        # view.__discriminator__(context, request) -> view's discriminator
        # so that superdynamic systems can feed the discriminator to
        # the introspection system to get info about it
        view = self.match(context, request)
        return view.__discriminator__(context, request)

    def add(self, view, order, accept=None, phash=None):
        if phash is not None:
            for i, (s, v, h) in enumerate(list(self.views)):
                if phash == h:
                    self.views[i] = (order, view, phash)
                    return

        if accept is None or '*' in accept:
            self.views.append((order, view, phash))
            self.views.sort(key=operator.itemgetter(0))
        else:
            subset = self.media_views.setdefault(accept, [])
            for i, (s, v, h) in enumerate(list(subset)):
                if phash == h:
                    subset[i] = (order, view, phash)
                    return
            else:
                subset.append((order, view, phash))
                subset.sort(key=operator.itemgetter(0))
            accepts = set(self.accepts)
            accepts.add(accept)
            self.accepts = list(accepts) # dedupe

    def get_views(self, request):
        if self.accepts and hasattr(request, 'accept'):
            accepts = self.accepts[:]
            views = []
            while accepts:
                match = request.accept.best_match(accepts)
                if match is None:
                    break
                subset = self.media_views[match]
                views.extend(subset)
                accepts.remove(match)
            views.extend(self.views)
            return views
        return self.views

    def match(self, context, request):
        for order, view, phash in self.get_views(request):
            if not hasattr(view, '__predicated__'):
                return view
            if view.__predicated__(context, request):
                return view
        raise PredicateMismatch(self.name)

    def __permitted__(self, context, request):
        view = self.match(context, request)
        if hasattr(view, '__permitted__'):
            return view.__permitted__(context, request)
        return True

    def __call_permissive__(self, context, request):
        view = self.match(context, request)
        view = getattr(view, '__call_permissive__', view)
        return view(context, request)

    def __call__(self, context, request):
        for order, view, phash in self.get_views(request):
            try:
                return view(context, request)
            except PredicateMismatch:
                continue
        raise PredicateMismatch(self.name)

class ViewsConfiguratorMixin(object):
    @viewdefaults
    @action_method
    def add_view(
        self,
        view=None,
        name="",
        for_=None,
        permission=None,
        request_type=None,
        route_name=None,
        request_method=None,
        request_param=None,
        containment=None,
        attr=None,
        renderer=None,
        wrapper=None,
        xhr=None,
        accept=None,
        header=None,
        path_info=None,
        custom_predicates=(),
        context=None,
        decorator=None,
        mapper=None,
        http_cache=None,
        match_param=None,
        check_csrf=None,
        **view_options):
        """ Add a :term:`view configuration` to the current
        configuration state.  Arguments to ``add_view`` are broken
        down below into *predicate* arguments and *non-predicate*
        arguments.  Predicate arguments narrow the circumstances in
        which the view callable will be invoked when a request is
        presented to :app:`Pyramid`; non-predicate arguments are
        informational.

        Non-Predicate Arguments

        view

          A :term:`view callable` or a :term:`dotted Python name`
          which refers to a view callable.  This argument is required
          unless a ``renderer`` argument also exists.  If a
          ``renderer`` argument is passed, and a ``view`` argument is
          not provided, the view callable defaults to a callable that
          returns an empty dictionary (see
          :ref:`views_which_use_a_renderer`).

        permission

          A :term:`permission` that the user must possess in order to invoke
          the :term:`view callable`.  See :ref:`view_security_section` for
          more information about view security and permissions.  This is
          often a string like ``view`` or ``edit``.

          If ``permission`` is omitted, a *default* permission may be used
          for this view registration if one was named as the
          :class:`pyramid.config.Configurator` constructor's
          ``default_permission`` argument, or if
          :meth:`pyramid.config.Configurator.set_default_permission` was used
          prior to this view registration.  Pass the value
          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission
          argument to explicitly indicate that the view should always be
          executable by entirely anonymous users, regardless of the default
          permission, bypassing any :term:`authorization policy` that may be
          in effect.

        attr

          This knob is most useful when the view definition is a class.

          The view machinery defaults to using the ``__call__`` method
          of the :term:`view callable` (or the function itself, if the
          view callable is a function) to obtain a response.  The
          ``attr`` value allows you to vary the method attribute used
          to obtain the response.  For example, if your view was a
          class, and the class has a method named ``index`` and you
          wanted to use this method instead of the class' ``__call__``
          method to return the response, you'd say ``attr="index"`` in the
          view configuration for the view.

        renderer

          This is either a single string term (e.g. ``json``) or a
          string implying a path or :term:`asset specification`
          (e.g. ``templates/views.pt``) naming a :term:`renderer`
          implementation.  If the ``renderer`` value does not contain
          a dot ``.``, the specified string will be used to look up a
          renderer implementation, and that renderer implementation
          will be used to construct a response from the view return
          value.  If the ``renderer`` value contains a dot (``.``),
          the specified term will be treated as a path, and the
          filename extension of the last element in the path will be
          used to look up the renderer implementation, which will be
          passed the full path.  The renderer implementation will be
          used to construct a :term:`response` from the view return
          value.

          Note that if the view itself returns a :term:`response` (see
          :ref:`the_response`), the specified renderer implementation
          is never called.

          When the renderer is a path, although a path is usually just
          a simple relative pathname (e.g. ``templates/foo.pt``,
          implying that a template named "foo.pt" is in the
          "templates" directory relative to the directory of the
          current :term:`package` of the Configurator), a path can be
          absolute, starting with a slash on UNIX or a drive letter
          prefix on Windows.  The path can alternately be a
          :term:`asset specification` in the form
          ``some.dotted.package_name:relative/path``, making it
          possible to address template assets which live in a
          separate package.

          The ``renderer`` attribute is optional.  If it is not
          defined, the "null" renderer is assumed (no rendering is
          performed and the value is passed back to the upstream
          :app:`Pyramid` machinery unmodified).

        http_cache

          .. versionadded:: 1.1

          When you supply an ``http_cache`` value to a view configuration,
          the ``Expires`` and ``Cache-Control`` headers of a response
          generated by the associated view callable are modified.  The value
          for ``http_cache`` may be one of the following:

          - A nonzero integer.  If it's a nonzero integer, it's treated as a
            number of seconds.  This number of seconds will be used to
            compute the ``Expires`` header and the ``Cache-Control:
            max-age`` parameter of responses to requests which call this view.
            For example: ``http_cache=3600`` instructs the requesting browser
            to 'cache this response for an hour, please'.

          - A ``datetime.timedelta`` instance.  If it's a
            ``datetime.timedelta`` instance, it will be converted into a
            number of seconds, and that number of seconds will be used to
            compute the ``Expires`` header and the ``Cache-Control:
            max-age`` parameter of responses to requests which call this view.
            For example: ``http_cache=datetime.timedelta(days=1)`` instructs
            the requesting browser to 'cache this response for a day, please'.

          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and
            ``Expires`` headers present in all responses from this view will
            be composed such that client browser cache (and any intermediate
            caches) are instructed to never cache the response.

          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,
            {'public':True})``), the first value in the tuple may be a
            nonzero integer or a ``datetime.timedelta`` instance; in either
            case this value will be used as the number of seconds to cache
            the response.  The second value in the tuple must be a
            dictionary.  The values present in the dictionary will be used as
            input to the ``Cache-Control`` response header.  For example:
            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,
            and add ``public`` to the Cache-Control header of the response'.
            All keys and values supported by the
            ``webob.cachecontrol.CacheControl`` interface may be added to the
            dictionary.  Supplying ``{'public':True}`` is equivalent to
            calling ``response.cache_control.public = True``.

          Providing a non-tuple value as ``http_cache`` is equivalent to
          calling ``response.cache_expires(value)`` within your view's body.

          Providing a two-tuple value as ``http_cache`` is equivalent to
          calling ``response.cache_expires(value[0], **value[1])`` within your
          view's body.

          If you wish to avoid influencing, the ``Expires`` header, and
          instead wish to only influence ``Cache-Control`` headers, pass a
          tuple as ``http_cache`` with the first element of ``None``, e.g.:
          ``(None, {'public':True})``.

          If you wish to prevent a view that uses ``http_cache`` in its
          configuration from having its caching response headers changed by
          this machinery, set ``response.cache_control.prevent_auto = True``
          before returning the response from the view.  This effectively
          disables any HTTP caching done by ``http_cache`` for that response.

        wrapper

          The :term:`view name` of a different :term:`view
          configuration` which will receive the response body of this
          view as the ``request.wrapped_body`` attribute of its own
          :term:`request`, and the :term:`response` returned by this
          view as the ``request.wrapped_response`` attribute of its
          own request.  Using a wrapper makes it possible to "chain"
          views together to form a composite response.  The response
          of the outermost wrapper view will be returned to the user.
          The wrapper view will be found as any view is found: see
          :ref:`view_lookup`.  The "best" wrapper view will be found
          based on the lookup ordering: "under the hood" this wrapper
          view is looked up via
          ``pyramid.view.render_view_to_response(context, request,
          'wrapper_viewname')``. The context and request of a wrapper
          view is the same context and request of the inner view.  If
          this attribute is unspecified, no view wrapping is done.

        decorator

          A :term:`dotted Python name` to function (or the function itself,
          or an iterable of the aforementioned) which will be used to
          decorate the registered :term:`view callable`.  The decorator
          function(s) will be called with the view callable as a single
          argument.  The view callable it is passed will accept
          ``(context, request)``.  The decorator(s) must return a
          replacement view callable which also accepts ``(context,
          request)``.

          If decorator is an iterable, the callables will be combined and
          used in the order provided as a decorator.
          For example::

            @view_config(...,
                decorator=(decorator2,
                           decorator1))
            def myview(request):
                ....

          Is similar to doing::

            @view_config(...)
            @decorator2
            @decorator1
            def myview(request):
                ...

          Except with the existing benefits of ``decorator=`` (having a common
          decorator syntax for all view calling conventions and not having to
          think about preserving function attributes such as ``__name__`` and
          ``__module__`` within decorator logic).

          All view callables in the decorator chain must return a response
          object implementing :class:`pyramid.interfaces.IResponse` or raise
          an exception:

          .. code-block:: python

             def log_timer(wrapped):
                 def wrapper(context, request):
                     start = time.time()
                     response = wrapped(context, request)
                     duration = time.time() - start
                     response.headers['X-View-Time'] = '%.3f' % (duration,)
                     log.info('view took %.3f seconds', duration)
                     return response
                 return wrapper

          .. versionchanged:: 1.4a4
             Passing an iterable.

        mapper

          A Python object or :term:`dotted Python name` which refers to a
          :term:`view mapper`, or ``None``.  By default it is ``None``, which
          indicates that the view should use the default view mapper.  This
          plug-point is useful for Pyramid extension developers, but it's not
          very useful for 'civilians' who are just developing stock Pyramid
          applications. Pay no attention to the man behind the curtain.

        accept

          This value represents a match query for one or more mimetypes in the
          ``Accept`` HTTP request header.  If this value is specified, it must
          be in one of the following forms: a mimetype match token in the form
          ``text/plain``, a wildcard mimetype match token in the form
          ``text/*`` or a match-all wildcard mimetype match token in the form
          ``*/*``.  If any of the forms matches the ``Accept`` header of the
          request, or if the ``Accept`` header isn't set at all in the request,
          this will match the current view. If this does not match the
          ``Accept`` header of the request, view matching continues.

        Predicate Arguments

        name

          The :term:`view name`.  Read :ref:`traversal_chapter` to
          understand the concept of a view name.

        context

          An object or a :term:`dotted Python name` referring to an
          interface or class object that the :term:`context` must be
          an instance of, *or* the :term:`interface` that the
          :term:`context` must provide in order for this view to be
          found and called.  This predicate is true when the
          :term:`context` is an instance of the represented class or
          if the :term:`context` provides the represented interface;
          it is otherwise false.  This argument may also be provided
          to ``add_view`` as ``for_`` (an older, still-supported
          spelling).

        route_name

          This value must match the ``name`` of a :term:`route
          configuration` declaration (see :ref:`urldispatch_chapter`)
          that must match before this view will be called.

        request_type

          This value should be an :term:`interface` that the
          :term:`request` must provide in order for this view to be
          found and called.  This value exists only for backwards
          compatibility purposes.

        request_method

          This value can be either a string (such as ``"GET"``, ``"POST"``,
          ``"PUT"``, ``"DELETE"``, ``"HEAD"`` or ``"OPTIONS"``) representing
          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of
          these strings.  A view declaration with this argument ensures that
          the view will only be called when the ``method`` attribute of the
          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches
          a supplied value.  Note that use of ``GET`` also implies that the
          view will respond to ``HEAD`` as of Pyramid 1.4.

          .. versionchanged:: 1.2
             The ability to pass a tuple of items as ``request_method``.
             Previous versions allowed only a string.

        request_param

          This value can be any string or any sequence of strings.  A view
          declaration with this argument ensures that the view will only be
          called when the :term:`request` has a key in the ``request.params``
          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a
          name which matches the supplied value (if the value is a string)
          or values (if the value is a tuple).  If any value
          supplied has a ``=`` sign in it,
          e.g. ``request_param="foo=123"``, then the key (``foo``)
          must both exist in the ``request.params`` dictionary, *and*
          the value must match the right hand side of the expression
          (``123``) for the view to "match" the current request.

        match_param

          .. versionadded:: 1.2

          This value can be a string of the format "key=value" or a tuple
          containing one or more of these strings.

          A view declaration with this argument ensures that the view will
          only be called when the :term:`request` has key/value pairs in its
          :term:`matchdict` that equal those supplied in the predicate.
          e.g. ``match_param="action=edit"`` would require the ``action``
          parameter in the :term:`matchdict` match the right hand side of
          the expression (``edit``) for the view to "match" the current
          request.

          If the ``match_param`` is a tuple, every key/value pair must match
          for the predicate to pass.

        containment

          This value should be a Python class or :term:`interface` (or a
          :term:`dotted Python name`) that an object in the
          :term:`lineage` of the context must provide in order for this view
          to be found and called.  The nodes in your object graph must be
          "location-aware" to use this feature.  See
          :ref:`location_aware` for more information about
          location-awareness.

        xhr

          This value should be either ``True`` or ``False``.  If this
          value is specified and is ``True``, the :term:`request`
          must possess an ``HTTP_X_REQUESTED_WITH`` (aka
          ``X-Requested-With``) header that has the value
          ``XMLHttpRequest`` for this view to be found and called.
          This is useful for detecting AJAX requests issued from
          jQuery, Prototype and other Javascript libraries.

        header

          This value represents an HTTP header name or a header
          name/value pair.  If the value contains a ``:`` (colon), it
          will be considered a name/value pair
          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The
          value portion should be a regular expression.  If the value
          does not contain a colon, the entire value will be
          considered to be the header name
          (e.g. ``If-Modified-Since``).  If the value evaluates to a
          header name only without a value, the header specified by
          the name must be present in the request for this predicate
          to be true.  If the value evaluates to a header name/value
          pair, the header specified by the name must be present in
          the request *and* the regular expression specified as the
          value must match the header value.  Whether or not the value
          represents a header name or a header name/value pair, the
          case of the header name is not significant.

        path_info

          This value represents a regular expression pattern that will
          be tested against the ``PATH_INFO`` WSGI environment
          variable.  If the regex matches, this predicate will be
          ``True``.

        check_csrf

          If specified, this value should be one of ``None``, ``True``,
          ``False``, or a string representing the 'check name'.  If the value
          is ``True`` or a string, CSRF checking will be performed.  If the
          value is ``False`` or ``None``, CSRF checking will not be performed.

          If the value provided is a string, that string will be used as the
          'check name'.  If the value provided is ``True``, ``csrf_token`` will
          be used as the check name.

          If CSRF checking is performed, the checked value will be the value
          of ``request.params[check_name]``.  This value will be compared
          against the value of ``request.session.get_csrf_token()``, and the
          check will pass if these two values are the same.  If the check
          passes, the associated view will be permitted to execute.  If the
          check fails, the associated view will not be permitted to execute.

          Note that using this feature requires a :term:`session factory` to
          have been configured.

          .. versionadded:: 1.4a2

        physical_path

          If specified, this value should be a string or a tuple representing
          the :term:`physical path` of the context found via traversal for this
          predicate to match as true.  For example: ``physical_path='/'`` or
          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.
          This is not a path prefix match or a regex, it's a whole-path match.
          It's useful when you want to always potentially show a view when some
          object is traversed to, but you can't be sure about what kind of
          object it will be, so you can't use the ``context`` predicate.  The
          individual path elements inbetween slash characters or in tuple
          elements should be the Unicode representation of the name of the
          resource and should not be encoded in any way.

          .. versionadded:: 1.4a3

        effective_principals

          If specified, this value should be a :term:`principal` identifier or
          a sequence of principal identifiers.  If the
          :attr:`pyramid.request.Request.effective_principals` property
          indicates that every principal named in the argument list is present
          in the current request, this predicate will return True; otherwise it
          will return False.  For example:
          ``effective_principals=pyramid.security.Authenticated`` or
          ``effective_principals=('fred', 'group:admins')``.

          .. versionadded:: 1.4a4

        custom_predicates

            .. deprecated:: 1.5
                This value should be a sequence of references to custom
                predicate callables.  Use custom predicates when no set of
                predefined predicates do what you need.  Custom predicates
                can be combined with predefined predicates as necessary.
                Each custom predicate callable should accept two arguments:
                ``context`` and ``request`` and should return either
                ``True`` or ``False`` after doing arbitrary evaluation of
                the context and/or the request.  The ``predicates`` argument
                to this method and the ability to register third-party view
                predicates via
                :meth:`pyramid.config.Configurator.add_view_predicate`
                obsoletes this argument, but it is kept around for backwards
                compatibility.

        view_options:

          Pass a key/value pair here to use a third-party predicate or set a
          value for a view deriver. See
          :meth:`pyramid.config.Configurator.add_view_predicate` and
          :meth:`pyramid.config.Configurator.add_view_deriver`. See
          :ref:`view_and_route_predicates` for more information about
          third-party predicates and :ref:`view_derivers` for information
          about view derivers.

          .. versionadded: 1.4a1

          .. versionchanged: 1.7

             Support setting view deriver options. Previously, only custom
             view predicate values could be supplied.

        """
        if custom_predicates:
            warnings.warn(
                ('The "custom_predicates" argument to Configurator.add_view '
                 'is deprecated as of Pyramid 1.5.  Use '
                 '"config.add_view_predicate" and use the registered '
                 'view predicate as a predicate argument to add_view instead. '
                 'See "Adding A Third Party View, Route, or Subscriber '
                 'Predicate" in the "Hooks" chapter of the documentation '
                 'for more information.'),
                DeprecationWarning,
                stacklevel=4
                )

        view = self.maybe_dotted(view)
        context = self.maybe_dotted(context)
        for_ = self.maybe_dotted(for_)
        containment = self.maybe_dotted(containment)
        mapper = self.maybe_dotted(mapper)

        def combine(*decorators):
            def decorated(view_callable):
                # reversed() allows a more natural ordering in the api
                for decorator in reversed(decorators):
                    view_callable = decorator(view_callable)
                return view_callable
            return decorated

        if is_nonstr_iter(decorator):
            decorator = combine(*map(self.maybe_dotted, decorator))
        else:
            decorator = self.maybe_dotted(decorator)

        if not view:
            if renderer:
                def view(context, request):
                    return {}
            else:
                raise ConfigurationError('"view" was not specified and '
                                         'no "renderer" specified')

        if request_type is not None:
            request_type = self.maybe_dotted(request_type)
            if not IInterface.providedBy(request_type):
                raise ConfigurationError(
                    'request_type must be an interface, not %s' % request_type)

        if context is None:
            context = for_

        r_context = context
        if r_context is None:
            r_context = Interface
        if not IInterface.providedBy(r_context):
            r_context = implementedBy(r_context)

        if isinstance(renderer, string_types):
            renderer = renderers.RendererHelper(
                name=renderer, package=self.package,
                registry=self.registry)

        if accept is not None:
            accept = accept.lower()

        introspectables = []
        ovals = view_options.copy()
        ovals.update(dict(
            xhr=xhr,
            request_method=request_method,
            path_info=path_info,
            request_param=request_param,
            header=header,
            accept=accept,
            containment=containment,
            request_type=request_type,
            match_param=match_param,
            check_csrf=check_csrf,
            custom=predvalseq(custom_predicates),
        ))

        def discrim_func():
            # We need to defer the discriminator until we know what the phash
            # is.  It can't be computed any sooner because thirdparty
            # predicates/view derivers may not yet exist when add_view is
            # called.
            valid_predicates = predlist.names()
            pvals = {}
            dvals = {}

            for (k, v) in ovals.items():
                if k in valid_predicates:
                    pvals[k] = v
                else:
                    dvals[k] = v

            self._check_view_options(**dvals)

            order, preds, phash = predlist.make(self, **pvals)

            view_intr.update({
                'phash': phash,
                'order': order,
                'predicates': preds,
                })
            return ('view', context, name, route_name, phash)

        discriminator = Deferred(discrim_func)

        if inspect.isclass(view) and attr:
            view_desc = 'method %r of %s' % (
                attr, self.object_description(view))
        else:
            view_desc = self.object_description(view)

        tmpl_intr = None

        view_intr = self.introspectable('views',
                                        discriminator,
                                        view_desc,
                                        'view')
        view_intr.update(dict(
            name=name,
            context=context,
            containment=containment,
            request_param=request_param,
            request_methods=request_method,
            route_name=route_name,
            attr=attr,
            xhr=xhr,
            accept=accept,
            header=header,
            path_info=path_info,
            match_param=match_param,
            check_csrf=check_csrf,
            callable=view,
            mapper=mapper,
            decorator=decorator,
        ))
        view_intr.update(view_options)
        introspectables.append(view_intr)
        predlist = self.get_predlist('view')

        def register(permission=permission, renderer=renderer):
            request_iface = IRequest
            if route_name is not None:
                request_iface = self.registry.queryUtility(IRouteRequest,
                                                           name=route_name)
                if request_iface is None:
                    # route configuration should have already happened in
                    # phase 2
                    raise ConfigurationError(
                        'No route named %s found for view registration' %
                        route_name)

            if renderer is None:
                # use default renderer if one exists (reg'd in phase 1)
                if self.registry.queryUtility(IRendererFactory) is not None:
                    renderer = renderers.RendererHelper(
                        name=None,
                        package=self.package,
                        registry=self.registry
                        )

            if permission is None:
                # intent: will be None if no default permission is registered
                # (reg'd in phase 1)
                permission = self.registry.queryUtility(IDefaultPermission)

            # added by discrim_func above during conflict resolving
            preds = view_intr['predicates']
            order = view_intr['order']
            phash = view_intr['phash']

            # __no_permission_required__ handled by _secure_view
            derived_view = self._derive_view(
                view,
                permission=permission,
                predicates=preds,
                attr=attr,
                context=context,
                renderer=renderer,
                wrapper_viewname=wrapper,
                viewname=name,
                accept=accept,
                order=order,
                phash=phash,
                decorator=decorator,
                mapper=mapper,
                http_cache=http_cache,
                extra_options=ovals,
            )
            derived_view.__discriminator__ = lambda *arg: discriminator
            # __discriminator__ is used by superdynamic systems
            # that require it for introspection after manual view lookup;
            # see also MultiView.__discriminator__
            view_intr['derived_callable'] = derived_view

            registered = self.registry.adapters.registered

            # A multiviews is a set of views which are registered for
            # exactly the same context type/request type/name triad.  Each
            # consituent view in a multiview differs only by the
            # predicates which it possesses.

            # To find a previously registered view for a context
            # type/request type/name triad, we need to use the
            # ``registered`` method of the adapter registry rather than
            # ``lookup``.  ``registered`` ignores interface inheritance
            # for the required and provided arguments, returning only a
            # view registered previously with the *exact* triad we pass
            # in.

            # We need to do this three times, because we use three
            # different interfaces as the ``provided`` interface while
            # doing registrations, and ``registered`` performs exact
            # matches on all the arguments it receives.

            old_view = None

            for view_type in (IView, ISecuredView, IMultiView):
                old_view = registered((IViewClassifier, request_iface,
                                       r_context), view_type, name)
                if old_view is not None:
                    break

            isexc = isexception(context)

            def regclosure():
                if hasattr(derived_view, '__call_permissive__'):
                    view_iface = ISecuredView
                else:
                    view_iface = IView
                self.registry.registerAdapter(
                    derived_view,
                    (IViewClassifier, request_iface, context), view_iface, name
                    )
                if isexc:
                    self.registry.registerAdapter(
                        derived_view,
                        (IExceptionViewClassifier, request_iface, context),
                        view_iface, name)

            is_multiview = IMultiView.providedBy(old_view)
            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)

            if old_view is None:
                # - No component was yet registered for any of our I*View
                #   interfaces exactly; this is the first view for this
                #   triad.
                regclosure()

            elif (not is_multiview) and (old_phash == phash):
                # - A single view component was previously registered with
                #   the same predicate hash as this view; this registration
                #   is therefore an override.
                regclosure()

            else:
                # - A view or multiview was already registered for this
                #   triad, and the new view is not an override.

                # XXX we could try to be more efficient here and register
                # a non-secured view for a multiview if none of the
                # multiview's consituent views have a permission
                # associated with them, but this code is getting pretty
                # rough already
                if is_multiview:
                    multiview = old_view
                else:
                    multiview = MultiView(name)
                    old_accept = getattr(old_view, '__accept__', None)
                    old_order = getattr(old_view, '__order__', MAX_ORDER)
                    multiview.add(old_view, old_order, old_accept, old_phash)
                multiview.add(derived_view, order, accept, phash)
                for view_type in (IView, ISecuredView):
                    # unregister any existing views
                    self.registry.adapters.unregister(
                        (IViewClassifier, request_iface, r_context),
                        view_type, name=name)
                    if isexc:
                        self.registry.adapters.unregister(
                            (IExceptionViewClassifier, request_iface,
                             r_context), view_type, name=name)
                self.registry.registerAdapter(
                    multiview,
                    (IViewClassifier, request_iface, context),
                    IMultiView, name=name)
                if isexc:
                    self.registry.registerAdapter(
                        multiview,
                        (IExceptionViewClassifier, request_iface, context),
                        IMultiView, name=name)

            self.registry._clear_view_lookup_cache()
            renderer_type = getattr(renderer, 'type', None) # gard against None
            intrspc = self.introspector
            if (
                renderer_type is not None and
                tmpl_intr is not None and
                intrspc is not None and
                intrspc.get('renderer factories', renderer_type) is not None
                ):
                # allow failure of registered template factories to be deferred
                # until view execution, like other bad renderer factories; if
                # we tried to relate this to an existing renderer factory
                # without checking if it the factory actually existed, we'd end
                # up with a KeyError at startup time, which is inconsistent
                # with how other bad renderer registrations behave (they throw
                # a ValueError at view execution time)
                tmpl_intr.relate('renderer factories', renderer.type)

        if mapper:
            mapper_intr = self.introspectable(
                'view mappers',
                discriminator,
                'view mapper for %s' % view_desc,
                'view mapper'
                )
            mapper_intr['mapper'] = mapper
            mapper_intr.relate('views', discriminator)
            introspectables.append(mapper_intr)
        if route_name:
            view_intr.relate('routes', route_name) # see add_route
        if renderer is not None and renderer.name and '.' in renderer.name:
            # the renderer is a template
            tmpl_intr = self.introspectable(
                'templates',
                discriminator,
                renderer.name,
                'template'
                )
            tmpl_intr.relate('views', discriminator)
            tmpl_intr['name'] = renderer.name
            tmpl_intr['type'] = renderer.type
            tmpl_intr['renderer'] = renderer
            introspectables.append(tmpl_intr)
        if permission is not None:
            # if a permission exists, register a permission introspectable
            perm_intr = self.introspectable(
                'permissions',
                permission,
                permission,
                'permission'
                )
            perm_intr['value'] = permission
            perm_intr.relate('views', discriminator)
            introspectables.append(perm_intr)
        self.action(discriminator, register, introspectables=introspectables)

    def _check_view_options(self, **kw):
        # we only need to validate deriver options because the predicates
        # were checked by the predlist
        derivers = self.registry.getUtility(IViewDerivers)
        for deriver in derivers.values():
            for opt in getattr(deriver, 'options', []):
                kw.pop(opt, None)
        if kw:
            raise ConfigurationError('Unknown view options: %s' % (kw,))

    def _apply_view_derivers(self, info):
        d = pyramid.viewderivers

        # These derivers are not really derivers and so have fixed order
        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),
                          ('predicated_view', d.predicated_view)]

        view = info.original_view
        derivers = self.registry.getUtility(IViewDerivers)
        for name, deriver in reversed(outer_derivers + derivers.sorted()):
            view = wraps_view(deriver)(view, info)
        return view

    @action_method
    def add_view_predicate(self, name, factory, weighs_more_than=None,
                           weighs_less_than=None):
        """
        .. versionadded:: 1.4

        Adds a view predicate factory.  The associated view predicate can
        later be named as a keyword argument to
        :meth:`pyramid.config.Configurator.add_view` in the
        ``predicates`` anonyous keyword argument dictionary.

        ``name`` should be the name of the predicate.  It must be a valid
        Python identifier (it will be used as a keyword argument to
        ``add_view`` by others).

        ``factory`` should be a :term:`predicate factory` or :term:`dotted
        Python name` which refers to a predicate factory.

        See :ref:`view_and_route_predicates` for more information.
        """
        self._add_predicate(
            'view',
            name,
            factory,
            weighs_more_than=weighs_more_than,
            weighs_less_than=weighs_less_than
            )

    def add_default_view_predicates(self):
        p = pyramid.config.predicates
        for (name, factory) in (
            ('xhr', p.XHRPredicate),
            ('request_method', p.RequestMethodPredicate),
            ('path_info', p.PathInfoPredicate),
            ('request_param', p.RequestParamPredicate),
            ('header', p.HeaderPredicate),
            ('accept', p.AcceptPredicate),
            ('containment', p.ContainmentPredicate),
            ('request_type', p.RequestTypePredicate),
            ('match_param', p.MatchParamPredicate),
            ('check_csrf', p.CheckCSRFTokenPredicate),
            ('physical_path', p.PhysicalPathPredicate),
            ('effective_principals', p.EffectivePrincipalsPredicate),
            ('custom', p.CustomPredicate),
            ):
            self.add_view_predicate(name, factory)

    @action_method
    def add_view_deriver(self, deriver, name=None, under=None, over=None):
        """
        .. versionadded:: 1.7

        Add a :term:`view deriver` to the view pipeline. View derivers are
        a feature used by extension authors to wrap views in custom code
        controllable by view-specific options.

        ``deriver`` should be a callable conforming to the
        :class:`pyramid.interfaces.IViewDeriver` interface.

        ``name`` should be the name of the view deriver.  There are no
        restrictions on the name of a view deriver. If left unspecified, the
        name will be constructed from the name of the ``deriver``.

        The ``under`` and ``over`` options can be used to control the ordering
        of view derivers by providing hints about where in the view pipeline
        the deriver is used. Each option may be a string or a list of strings.
        At least one view deriver in each, the over and under directions, must
        exist to fully satisfy the constraints.

        ``under`` means closer to the user-defined :term:`view callable`,
        and ``over`` means closer to view pipeline ingress.

        Specifying neither ``under`` nor ``over`` is equivalent to specifying
        ``over='rendered_view'`` and ``under='decorated_view'``, placing the
        deriver somewhere between the ``decorated_view`` and ``rendered_view``
        derivers.

        See :ref:`view_derivers` for more information.

        """
        deriver = self.maybe_dotted(deriver)

        if name is None:
            name = deriver.__name__

        if name in (INGRESS,):
            raise ConfigurationError('%s is a reserved view deriver name'
                                     % name)

        if under is None and over is None:
            under = 'decorated_view'
            over = 'rendered_view'

        if over is None and name != MAPPED_VIEW:
            raise ConfigurationError('must specify an "over" constraint for '
                                     'the %s view deriver' % name)
        elif over is not None:
            over = as_sorted_tuple(over)

        if under is None:
            raise ConfigurationError('must specify an "under" constraint for '
                                     'the %s view deriver' % name)
        else:
            under = as_sorted_tuple(under)

        if over is not None and INGRESS in over:
            raise ConfigurationError('%s cannot be over view deriver INGRESS'
                                     % name)

        if MAPPED_VIEW in under:
            raise ConfigurationError('%s cannot be under view deriver '
                                     'MAPPED_VIEW' % name)

        discriminator = ('view deriver', name)
        intr = self.introspectable(
            'view derivers',
            name,
            name,
            'view deriver')
        intr['name'] = name
        intr['deriver'] = deriver
        intr['under'] = under
        intr['over'] = over
        def register():
            derivers = self.registry.queryUtility(IViewDerivers)
            if derivers is None:
                derivers = TopologicalSorter(
                    default_before=None,
                    default_after=INGRESS,
                    first=INGRESS,
                    last=MAPPED_VIEW,
                )
                self.registry.registerUtility(derivers, IViewDerivers)
            derivers.add(name, deriver, before=over, after=under)
        self.action(discriminator, register, introspectables=(intr,),
                    order=PHASE1_CONFIG) # must be registered before add_view

    def add_default_view_derivers(self):
        d = pyramid.viewderivers
        derivers = [
            ('secured_view', d.secured_view),
            ('owrapped_view', d.owrapped_view),
            ('http_cached_view', d.http_cached_view),
            ('decorated_view', d.decorated_view),
            ('rendered_view', d.rendered_view),
        ]
        last = INGRESS
        for name, deriver in derivers:
            self.add_view_deriver(
                deriver,
                name=name,
                under=last,
                over=MAPPED_VIEW,
            )
            last = name

        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)

    def derive_view(self, view, attr=None, renderer=None):
        """
        Create a :term:`view callable` using the function, instance,
        or class (or :term:`dotted Python name` referring to the same)
        provided as ``view`` object.

        .. warning::

           This method is typically only used by :app:`Pyramid` framework
           extension authors, not by :app:`Pyramid` application developers.

        This is API is useful to framework extenders who create
        pluggable systems which need to register 'proxy' view
        callables for functions, instances, or classes which meet the
        requirements of being a :app:`Pyramid` view callable.  For
        example, a ``some_other_framework`` function in another
        framework may want to allow a user to supply a view callable,
        but he may want to wrap the view callable in his own before
        registering the wrapper as a :app:`Pyramid` view callable.
        Because a :app:`Pyramid` view callable can be any of a
        number of valid objects, the framework extender will not know
        how to call the user-supplied object.  Running it through
        ``derive_view`` normalizes it to a callable which accepts two
        arguments: ``context`` and ``request``.

        For example:

        .. code-block:: python

           def some_other_framework(user_supplied_view):
               config = Configurator(reg)
               proxy_view = config.derive_view(user_supplied_view)
               def my_wrapper(context, request):
                   do_something_that_mutates(request)
                   return proxy_view(context, request)
               config.add_view(my_wrapper)

        The ``view`` object provided should be one of the following:

        - A function or another non-class callable object that accepts
          a :term:`request` as a single positional argument and which
          returns a :term:`response` object.

        - A function or other non-class callable object that accepts
          two positional arguments, ``context, request`` and which
          returns a :term:`response` object.

        - A class which accepts a single positional argument in its
          constructor named ``request``, and which has a ``__call__``
          method that accepts no arguments that returns a
          :term:`response` object.

        - A class which accepts two positional arguments named
          ``context, request``, and which has a ``__call__`` method
          that accepts no arguments that returns a :term:`response`
          object.

        - A :term:`dotted Python name` which refers to any of the
          kinds of objects above.

        This API returns a callable which accepts the arguments
        ``context, request`` and which returns the result of calling
        the provided ``view`` object.

        The ``attr`` keyword argument is most useful when the view
        object is a class.  It names the method that should be used as
        the callable.  If ``attr`` is not provided, the attribute
        effectively defaults to ``__call__``.  See
        :ref:`class_as_view` for more information.

        The ``renderer`` keyword argument should be a renderer
        name. If supplied, it will cause the returned callable to use
        a :term:`renderer` to convert the user-supplied view result to
        a :term:`response` object.  If a ``renderer`` argument is not
        supplied, the user-supplied view must itself return a
        :term:`response` object.  """
        return self._derive_view(view, attr=attr, renderer=renderer)

    # b/w compat
    def _derive_view(self, view, permission=None, predicates=(),
                     attr=None, renderer=None, wrapper_viewname=None,
                     viewname=None, accept=None, order=MAX_ORDER,
                     phash=DEFAULT_PHASH, decorator=None,
                     mapper=None, http_cache=None, context=None,
                     extra_options=None):
        view = self.maybe_dotted(view)
        mapper = self.maybe_dotted(mapper)
        if isinstance(renderer, string_types):
            renderer = renderers.RendererHelper(
                name=renderer, package=self.package,
                registry=self.registry)
        if renderer is None:
            # use default renderer if one exists
            if self.registry.queryUtility(IRendererFactory) is not None:
                renderer = renderers.RendererHelper(
                    name=None,
                    package=self.package,
                    registry=self.registry)

        options = dict(
            view=view,
            context=context,
            permission=permission,
            attr=attr,
            renderer=renderer,
            wrapper=wrapper_viewname,
            name=viewname,
            accept=accept,
            mapper=mapper,
            decorator=decorator,
            http_cache=http_cache,
        )
        if extra_options:
            options.update(extra_options)

        info = ViewDeriverInfo(
            view=view,
            registry=self.registry,
            package=self.package,
            predicates=predicates,
            options=options,
        )

        # order and phash are only necessary for the predicated view and
        # are not really view deriver options
        info.order = order
        info.phash = phash

        return self._apply_view_derivers(info)

    @viewdefaults
    @action_method
    def add_forbidden_view(
        self,
        view=None,
        attr=None,
        renderer=None,
        wrapper=None,
        route_name=None,
        request_type=None,
        request_method=None,
        request_param=None,
        containment=None,
        xhr=None,
        accept=None,
        header=None,
        path_info=None,
        custom_predicates=(),
        decorator=None,
        mapper=None,
        match_param=None,
        **view_options
        ):
        """ Add a forbidden view to the current configuration state.  The
        view will be called when Pyramid or application code raises a
        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of
        circumstances implied by the predicates provided are matched.  The
        simplest example is:

          .. code-block:: python

            def forbidden(request):
                return Response('Forbidden', status='403 Forbidden')

            config.add_forbidden_view(forbidden)

        If ``view`` argument is not provided, the view callable defaults to
        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.

        All arguments have the same meaning as
        :meth:`pyramid.config.Configurator.add_view` and each predicate
        argument restricts the set of circumstances under which this forbidden
        view will be invoked.  Unlike
        :meth:`pyramid.config.Configurator.add_view`, this method will raise
        an exception if passed ``name``, ``permission``, ``context``,
        ``for_``, or ``http_cache`` keyword arguments.  These argument values
        make no sense in the context of a forbidden view.

        .. versionadded:: 1.3
        """
        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):
            if arg in view_options:
                raise ConfigurationError(
                    '%s may not be used as an argument to add_forbidden_view'
                    % arg
                    )

        if view is None:
            view = default_exceptionresponse_view

        settings = dict(
            view=view,
            context=HTTPForbidden,
            wrapper=wrapper,
            request_type=request_type,
            request_method=request_method,
            request_param=request_param,
            containment=containment,
            xhr=xhr,
            accept=accept,
            header=header,
            path_info=path_info,
            custom_predicates=custom_predicates,
            decorator=decorator,
            mapper=mapper,
            match_param=match_param,
            route_name=route_name,
            permission=NO_PERMISSION_REQUIRED,
            attr=attr,
            renderer=renderer,
            )
        settings.update(view_options)
        return self.add_view(**settings)

    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias

    @viewdefaults
    @action_method
    def add_notfound_view(
        self,
        view=None,
        attr=None,
        renderer=None,
        wrapper=None,
        route_name=None,
        request_type=None,
        request_method=None,
        request_param=None,
        containment=None,
        xhr=None,
        accept=None,
        header=None,
        path_info=None,
        custom_predicates=(),
        decorator=None,
        mapper=None,
        match_param=None,
        append_slash=False,
        **view_options
        ):
        """ Add a default Not Found View to the current configuration state.
        The view will be called when Pyramid or application code raises an
        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a
        view cannot be found for the request).  The simplest example is:

          .. code-block:: python

            def notfound(request):
                return Response('Not Found', status='404 Not Found')

            config.add_notfound_view(notfound)

        If ``view`` argument is not provided, the view callable defaults to
        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.

        All arguments except ``append_slash`` have the same meaning as
        :meth:`pyramid.config.Configurator.add_view` and each predicate
        argument restricts the set of circumstances under which this notfound
        view will be invoked.  Unlike
        :meth:`pyramid.config.Configurator.add_view`, this method will raise
        an exception if passed ``name``, ``permission``, ``context``,
        ``for_``, or ``http_cache`` keyword arguments.  These argument values
        make no sense in the context of a Not Found View.

        If ``append_slash`` is ``True``, when this Not Found View is invoked,
        and the current path info does not end in a slash, the notfound logic
        will attempt to find a :term:`route` that matches the request's path
        info suffixed with a slash.  If such a route exists, Pyramid will
        issue a redirect to the URL implied by the route; if it does not,
        Pyramid will return the result of the view callable provided as
        ``view``, as normal.

        If the argument provided as ``append_slash`` is not a boolean but
        instead implements :class:`~pyramid.interfaces.IResponse`, the
        append_slash logic will behave as if ``append_slash=True`` was passed,
        but the provided class will be used as the response class instead of
        the default :class:`~pyramid.httpexceptions.HTTPFound` response class
        when a redirect is performed.  For example:

          .. code-block:: python

            from pyramid.httpexceptions import HTTPMovedPermanently
            config.add_notfound_view(append_slash=HTTPMovedPermanently)

        The above means that a redirect to a slash-appended route will be
        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`
        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will
        be used` for the redirect response if a slash-appended route is found.

        .. versionchanged:: 1.6
        .. versionadded:: 1.3
        """
        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):
            if arg in view_options:
                raise ConfigurationError(
                    '%s may not be used as an argument to add_notfound_view'
                    % arg
                    )

        if view is None:
            view = default_exceptionresponse_view

        settings = dict(
            view=view,
            context=HTTPNotFound,
            wrapper=wrapper,
            request_type=request_type,
            request_method=request_method,
            request_param=request_param,
            containment=containment,
            xhr=xhr,
            accept=accept,
            header=header,
            path_info=path_info,
            custom_predicates=custom_predicates,
            decorator=decorator,
            mapper=mapper,
            match_param=match_param,
            route_name=route_name,
            permission=NO_PERMISSION_REQUIRED,
            )
        settings.update(view_options)
        if append_slash:
            view = self._derive_view(view, attr=attr, renderer=renderer)
            if IResponse.implementedBy(append_slash):
                view = AppendSlashNotFoundViewFactory(
                    view, redirect_class=append_slash,
                )
            else:
                view = AppendSlashNotFoundViewFactory(view)
            settings['view'] = view
        else:
            settings['attr'] = attr
            settings['renderer'] = renderer
        return self.add_view(**settings)

    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias

    @action_method
    def set_view_mapper(self, mapper):
        """
        Setting a :term:`view mapper` makes it possible to make use of
        :term:`view callable` objects which implement different call
        signatures than the ones supported by :app:`Pyramid` as described in
        its narrative documentation.

        The ``mapper`` argument should be an object implementing
        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted
        Python name` to such an object.  The provided ``mapper`` will become
        the default view mapper to be used by all subsequent :term:`view
        configuration` registrations.

        .. seealso::

            See also :ref:`using_a_view_mapper`.

        .. note::

           Using the ``default_view_mapper`` argument to the
           :class:`pyramid.config.Configurator` constructor
           can be used to achieve the same purpose.
        """
        mapper = self.maybe_dotted(mapper)
        def register():
            self.registry.registerUtility(mapper, IViewMapperFactory)
        # IViewMapperFactory is looked up as the result of view config
        # in phase 3
        intr = self.introspectable('view mappers',
                                   IViewMapperFactory,
                                   self.object_description(mapper),
                                   'default view mapper')
        intr['mapper'] = mapper
        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,
                    introspectables=(intr,))

    @action_method
    def add_static_view(self, name, path, **kw):
        """ Add a view used to render static assets such as images
        and CSS files.

        The ``name`` argument is a string representing an
        application-relative local URL prefix.  It may alternately be a full
        URL.

        The ``path`` argument is the path on disk where the static files
        reside.  This can be an absolute path, a package-relative path, or a
        :term:`asset specification`.

        The ``cache_max_age`` keyword argument is input to set the
        ``Expires`` and ``Cache-Control`` headers for static assets served.
        Note that this argument has no effect when the ``name`` is a *url
        prefix*.  By default, this argument is ``None``, meaning that no
        particular Expires or Cache-Control headers are set in the response.

        The ``permission`` keyword argument is used to specify the
        :term:`permission` required by a user to execute the static view.  By
        default, it is the string
        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel
        which indicates that, even if a :term:`default permission` exists for
        the current application, the static view should be renderered to
        completely anonymous users.  This default value is permissive
        because, in most web apps, static assets seldom need protection from
        viewing.  If ``permission`` is specified, the security checking will
        be performed against the default root factory ACL.

        Any other keyword arguments sent to ``add_static_view`` are passed on
        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,
        perhaps to define a custom factory with a custom ACL for this static
        view).

        *Usage*

        The ``add_static_view`` function is typically used in conjunction
        with the :meth:`pyramid.request.Request.static_url` method.
        ``add_static_view`` adds a view which renders a static asset when
        some URL is visited; :meth:`pyramid.request.Request.static_url`
        generates a URL to that asset.

        The ``name`` argument to ``add_static_view`` is usually a simple URL
        prefix (e.g. ``'images'``).  When this is the case, the
        :meth:`pyramid.request.Request.static_url` API will generate a URL
        which points to a Pyramid view, which will serve up a set of assets
        that live in the package itself. For example:

        .. code-block:: python

           add_static_view('images', 'mypackage:images/')

        Code that registers such a view can generate URLs to the view via
        :meth:`pyramid.request.Request.static_url`:

        .. code-block:: python

           request.static_url('mypackage:images/logo.png')

        When ``add_static_view`` is called with a ``name`` argument that
        represents a URL prefix, as it is above, subsequent calls to
        :meth:`pyramid.request.Request.static_url` with paths that start with
        the ``path`` argument passed to ``add_static_view`` will generate a
        URL something like ``http://<Pyramid app URL>/images/logo.png``,
        which will cause the ``logo.png`` file in the ``images`` subdirectory
        of the ``mypackage`` package to be served.

        ``add_static_view`` can alternately be used with a ``name`` argument
        which is a *URL*, causing static assets to be served from an external
        webserver.  This happens when the ``name`` argument is a fully
        qualified URL (e.g. starts with ``http://`` or similar).  In this
        mode, the ``name`` is used as the prefix of the full URL when
        generating a URL using :meth:`pyramid.request.Request.static_url`.
        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)
        is used as the ``name`` argument, the generated URL will use the
        protocol of the request (http or https, respectively).

        For example, if ``add_static_view`` is called like so:

        .. code-block:: python

           add_static_view('http://example.com/images', 'mypackage:images/')

        Subsequently, the URLs generated by
        :meth:`pyramid.request.Request.static_url` for that static view will
        be prefixed with ``http://example.com/images`` (the external webserver
        listening on ``example.com`` must be itself configured to respond
        properly to such a request.):

        .. code-block:: python

           static_url('mypackage:images/logo.png', request)

        See :ref:`static_assets_section` for more information.
        """
        spec = self._make_spec(path)
        info = self._get_static_info()
        info.add(self, name, spec, **kw)

    def add_cache_buster(self, path, cachebust, explicit=False):
        """
        Add a cache buster to a set of files on disk.

        The ``path`` should be the path on disk where the static files
        reside.  This can be an absolute path, a package-relative path, or a
        :term:`asset specification`.

        The ``cachebust`` argument may be set to cause
        :meth:`~pyramid.request.Request.static_url` to use cache busting when
        generating URLs. See :ref:`cache_busting` for general information
        about cache busting. The value of the ``cachebust`` argument must
        be an object which implements
        :class:`~pyramid.interfaces.ICacheBuster`.

        If ``explicit`` is set to ``True`` then the ``path`` for the cache
        buster will be matched based on the ``rawspec`` instead of the
        ``pathspec`` as defined in the
        :class:`~pyramid.interfaces.ICacheBuster` interface.
        Default: ``False``.

        """
        spec = self._make_spec(path)
        info = self._get_static_info()
        info.add_cache_buster(self, spec, cachebust, explicit=explicit)

    def _get_static_info(self):
        info = self.registry.queryUtility(IStaticURLInfo)
        if info is None:
            info = StaticURLInfo()
            self.registry.registerUtility(info, IStaticURLInfo)
        return info

def isexception(o):
    if IInterface.providedBy(o):
        if IException.isEqualOrExtendedBy(o):
            return True
    return (
        isinstance(o, Exception) or
        (inspect.isclass(o) and (issubclass(o, Exception)))
        )

@implementer(IViewDeriverInfo)
class ViewDeriverInfo(object):
    def __init__(self, view, registry, package, predicates, options):
        self.original_view = view
        self.registry = registry
        self.package = package
        self.predicates = predicates or []
        self.options = options or {}

    @reify
    def settings(self):
        return self.registry.settings

@implementer(IStaticURLInfo)
class StaticURLInfo(object):
    def __init__(self):
        self.registrations = []
        self.cache_busters = []

    def generate(self, path, request, **kw):
        for (url, spec, route_name) in self.registrations:
            if path.startswith(spec):
                subpath = path[len(spec):]
                if WIN: # pragma: no cover
                    subpath = subpath.replace('\\', '/') # windows
                if self.cache_busters:
                    subpath, kw = self._bust_asset_path(
                        request, spec, subpath, kw)
                if url is None:
                    kw['subpath'] = subpath
                    return request.route_url(route_name, **kw)
                else:
                    app_url, scheme, host, port, qs, anchor = \
                        parse_url_overrides(kw)
                    parsed = url_parse(url)
                    if not parsed.scheme:
                        url = urlparse.urlunparse(parsed._replace(
                            scheme=request.environ['wsgi.url_scheme']))
                    subpath = url_quote(subpath)
                    result = urljoin(url, subpath)
                    return result + qs + anchor

        raise ValueError('No static URL definition matching %s' % path)

    def add(self, config, name, spec, **extra):
        # This feature only allows for the serving of a directory and
        # the files contained within, not of a single asset;
        # appending a slash here if the spec doesn't have one is
        # required for proper prefix matching done in ``generate``
        # (``subpath = path[len(spec):]``).
        if os.path.isabs(spec): # FBO windows
            sep = os.sep
        else:
            sep = '/'
        if not spec.endswith(sep) and not spec.endswith(':'):
            spec = spec + sep

        # we also make sure the name ends with a slash, purely as a
        # convenience: a name that is a url is required to end in a
        # slash, so that ``urljoin(name, subpath))`` will work above
        # when the name is a URL, and it doesn't hurt things for it to
        # have a name that ends in a slash if it's used as a route
        # name instead of a URL.
        if not name.endswith('/'):
            # make sure it ends with a slash
            name = name + '/'

        if url_parse(name).netloc:
            # it's a URL
            # url, spec, route_name
            url = name
            route_name = None
        else:
            # it's a view name
            url = None
            cache_max_age = extra.pop('cache_max_age', None)

            # create a view
            view = static_view(spec, cache_max_age=cache_max_age,
                               use_subpath=True)

            # Mutate extra to allow factory, etc to be passed through here.
            # Treat permission specially because we'd like to default to
            # permissiveness (see docs of config.add_static_view).
            permission = extra.pop('permission', None)
            if permission is None:
                permission = NO_PERMISSION_REQUIRED

            context = extra.pop('context', None)
            if context is None:
                context = extra.pop('for_', None)

            renderer = extra.pop('renderer', None)

            # register a route using the computed view, permission, and
            # pattern, plus any extras passed to us via add_static_view
            pattern = "%s*subpath" % name # name already ends with slash
            if config.route_prefix:
                route_name = '__%s/%s' % (config.route_prefix, name)
            else:
                route_name = '__%s' % name
            config.add_route(route_name, pattern, **extra)
            config.add_view(
                route_name=route_name,
                view=view,
                permission=permission,
                context=context,
                renderer=renderer,
            )

        def register():
            registrations = self.registrations

            names = [t[0] for t in registrations]

            if name in names:
                idx = names.index(name)
                registrations.pop(idx)

            # url, spec, route_name
            registrations.append((url, spec, route_name))

        intr = config.introspectable('static views',
                                     name,
                                     'static view for %r' % name,
                                     'static view')
        intr['name'] = name
        intr['spec'] = spec

        config.action(None, callable=register, introspectables=(intr,))

    def add_cache_buster(self, config, spec, cachebust, explicit=False):
        # ensure the spec always has a trailing slash as we only support
        # adding cache busters to folders, not files
        if os.path.isabs(spec): # FBO windows
            sep = os.sep
        else:
            sep = '/'
        if not spec.endswith(sep) and not spec.endswith(':'):
            spec = spec + sep

        def register():
            if config.registry.settings.get('pyramid.prevent_cachebust'):
                return

            cache_busters = self.cache_busters

            # find duplicate cache buster (old_idx)
            # and insertion location (new_idx)
            new_idx, old_idx = len(cache_busters), None
            for idx, (spec_, cb_, explicit_) in enumerate(cache_busters):
                # if we find an identical (spec, explicit) then use it
                if spec == spec_ and explicit == explicit_:
                    old_idx = new_idx = idx
                    break

                # past all explicit==False specs then add to the end
                elif not explicit and explicit_:
                    new_idx = idx
                    break

                # explicit matches and spec is shorter
                elif explicit == explicit_ and len(spec) < len(spec_):
                    new_idx = idx
                    break

            if old_idx is not None:
                cache_busters.pop(old_idx)

            cache_busters.insert(new_idx, (spec, cachebust, explicit))

        intr = config.introspectable('cache busters',
                                     spec,
                                     'cache buster for %r' % spec,
                                     'cache buster')
        intr['cachebust'] = cachebust
        intr['path'] = spec
        intr['explicit'] = explicit

        config.action(None, callable=register, introspectables=(intr,))

    def _bust_asset_path(self, request, spec, subpath, kw):
        registry = request.registry
        pkg_name, pkg_subpath = resolve_asset_spec(spec)
        rawspec = None

        if pkg_name is not None:
            pathspec = '{0}:{1}{2}'.format(pkg_name, pkg_subpath, subpath)
            overrides = registry.queryUtility(IPackageOverrides, name=pkg_name)
            if overrides is not None:
                resource_name = posixpath.join(pkg_subpath, subpath)
                sources = overrides.filtered_sources(resource_name)
                for source, filtered_path in sources:
                    rawspec = source.get_path(filtered_path)
                    if hasattr(source, 'pkg_name'):
                        rawspec = '{0}:{1}'.format(source.pkg_name, rawspec)
                    break

        else:
            pathspec = pkg_subpath + subpath

        if rawspec is None:
            rawspec = pathspec

        kw['pathspec'] = pathspec
        kw['rawspec'] = rawspec
        for spec_, cachebust, explicit in reversed(self.cache_busters):
            if (
                (explicit and rawspec.startswith(spec_)) or
                (not explicit and pathspec.startswith(spec_))
            ):
                subpath, kw = cachebust(request, subpath, kw)
                break
        return subpath, kw

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
### ImportError: Cannot Import 'VIEW' from 'pyramid.viewderivers'

#### Description
After updating the constraints for view derivers, attempting to import the `VIEW` constant from `pyramid.viewderivers` results in an `ImportError`. This prevents certain tests from running successfully and disrupts the configuration of view derivers.

#### Example Code
```python
from pyramid.viewderivers import VIEW

def test_add_deriver_enforces_view_is_last():
    from pyramid.exceptions import ConfigurationError

    def deriv1(view, info): pass
    try:
        config.add_view_deriver(deriv1, under=VIEW)
    except ConfigurationError as ex:
        assert 'cannot be under VIEW' in ex.args[0]
    else:
        raise AssertionError
```

#### Expected Behavior
The `VIEW` constant should be successfully imported from `pyramid.viewderivers`, allowing tests and configurations that rely on it to function correctly.

#### Actual Behavior
An `ImportError` is raised:
```
ImportError: cannot import name 'VIEW' from 'pyramid.viewderivers' (/path/to/pyramid/viewderivers.py)
```

This error indicates that the `VIEW` constant is either not defined or not properly exposed in the `pyramid.viewderivers` module after the recent commit.

[/ISSUE]
{
    "TestDeriveView.test_as_function_context_and_request": "PASSED",
    "TestDeriveView.test_as_function_requestonly": "PASSED",
    "TestDeriveView.test_as_instance_context_and_request": "PASSED",
    "TestDeriveView.test_as_instance_context_and_request_attr_and_renderer": "PASSED",
    "TestDeriveView.test_as_instance_requestonly_attr_and_renderer": "PASSED",
    "TestDeriveView.test_as_newstyle_class_context_and_request": "PASSED",
    "TestDeriveView.test_as_newstyle_class_context_and_request_attr_and_renderer": "PASSED",
    "TestDeriveView.test_as_newstyle_class_requestonly": "PASSED",
    "TestDeriveView.test_as_newstyle_class_requestonly_attr_and_renderer": "PASSED",
    "TestDeriveView.test_as_oldstyle_class_context_and_request": "PASSED",
    "TestDeriveView.test_as_oldstyle_class_requestonly": "PASSED",
    "TestDeriveView.test_as_oldstyle_cls_context_request_attr_and_renderer": "PASSED",
    "TestDeriveView.test_as_oldstyle_cls_requestonly_attr_and_renderer": "PASSED",
    "TestDeriveView.test_attr_wrapped_view_branching_default_phash": "PASSED",
    "TestDeriveView.test_attr_wrapped_view_branching_nondefault_phash": "PASSED",
    "TestDeriveView.test_class_with_attr": "PASSED",
    "TestDeriveView.test_class_without_attr": "PASSED",
    "TestDeriveView.test_debug_auth_permission_authpol_denied": "PASSED",
    "TestDeriveView.test_debug_auth_permission_authpol_denied2": "PASSED",
    "TestDeriveView.test_debug_auth_permission_authpol_overridden": "PASSED",
    "TestDeriveView.test_debug_auth_permission_authpol_permitted": "PASSED",
    "TestDeriveView.test_debug_auth_permission_authpol_permitted_no_request": "PASSED",
    "TestDeriveView.test_function_returns_true_Response_no_renderer": "PASSED",
    "TestDeriveView.test_function_returns_true_Response_with_renderer": "PASSED",
    "TestDeriveView.test_http_cached_prevent_http_cache_in_settings": "PASSED",
    "TestDeriveView.test_http_cached_view_bad_tuple": "PASSED",
    "TestDeriveView.test_http_cached_view_integer": "PASSED",
    "TestDeriveView.test_http_cached_view_prevent_auto_set": "PASSED",
    "TestDeriveView.test_http_cached_view_timedelta": "PASSED",
    "TestDeriveView.test_http_cached_view_tuple": "PASSED",
    "TestDeriveView.test_http_cached_view_tuple_seconds_None": "PASSED",
    "TestDeriveView.test_predicate_mismatch_exception_has_text_in_detail": "PASSED",
    "TestDeriveView.test_predicate_mismatch_view_has_name": "PASSED",
    "TestDeriveView.test_predicate_mismatch_view_has_no_name": "PASSED",
    "TestDeriveView.test_requestonly_function": "PASSED",
    "TestDeriveView.test_requestonly_function_with_renderer": "PASSED",
    "TestDeriveView.test_requestonly_function_with_renderer_request_has_view": "PASSED",
    "TestDeriveView.test_requestonly_function_with_renderer_request_override": "PASSED",
    "TestDeriveView.test_secured_view_authn_policy_no_authz_policy": "PASSED",
    "TestDeriveView.test_secured_view_authz_policy_no_authn_policy": "PASSED",
    "TestDeriveView.test_secured_view_raises_forbidden_no_name": "PASSED",
    "TestDeriveView.test_secured_view_raises_forbidden_with_name": "PASSED",
    "TestDeriveView.test_with_debug_authorization_authn_policy_no_authz_policy": "PASSED",
    "TestDeriveView.test_with_debug_authorization_authz_policy_no_authn_policy": "PASSED",
    "TestDeriveView.test_with_debug_authorization_no_authpol": "PASSED",
    "TestDeriveView.test_with_debug_authorization_no_permission": "PASSED",
    "TestDeriveView.test_with_predicates_all": "PASSED",
    "TestDeriveView.test_with_predicates_checker": "PASSED",
    "TestDeriveView.test_with_predicates_notall": "PASSED",
    "TestDeriveView.test_with_view_mapper_config_specified": "PASSED",
    "TestDeriveView.test_with_view_mapper_default_mapper_specified": "PASSED",
    "TestDeriveView.test_with_view_mapper_view_specified": "PASSED",
    "TestDeriveView.test_with_wrapper_viewname": "PASSED",
    "TestDeriveView.test_with_wrapper_viewname_notfound": "PASSED",
    "TestDerivationOrder.test_right_order_implicit": "PASSED",
    "TestDerivationOrder.test_right_order_under_rendered_view": "PASSED",
    "TestDerivationOrder.test_right_order_under_rendered_view_others": "PASSED",
    "TestDerivationOrder.test_right_order_user_sorted": "PASSED",
    "TestAddDeriver.test_add_deriver_enforces_ingress_is_first": "PASSED",
    "TestAddDeriver.test_add_deriver_enforces_mapped_view_is_last": "PASSED",
    "TestAddDeriver.test_add_deriver_enforces_view_is_last": "PASSED",
    "TestAddDeriver.test_add_deriver_reserves_ingress": "PASSED",
    "TestAddDeriver.test_add_deriver_without_name": "PASSED",
    "TestAddDeriver.test_add_multi_derivers_ordered": "PASSED",
    "TestAddDeriver.test_add_single_deriver": "PASSED",
    "TestAddDeriver.test_override_deriver": "PASSED",
    "TestAddDeriver.test_override_mapped_view": "PASSED",
    "TestDeriverIntegration.test_unexpected_view_options": "PASSED",
    "TestDeriverIntegration.test_view_options": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_object_event_subscriber": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_resource_url_default_resource_iface_means_Interface": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_resource_url_nodefault_resource_iface": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_response_adapter": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_response_adapter_dottednames": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_response_adapter_self": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_subscriber_defaults": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_subscriber_dottednames": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_subscriber_iface_specified": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_subscriber_predicate": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_subscriber_with_default_type_predicates_False": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_subscriber_with_default_type_predicates_True": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_subscriber_with_specific_type_and_predicates_False": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_subscriber_with_specific_type_and_predicates_True": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_traverser_default_iface_means_Interface": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_traverser_introspectables": "PASSED",
    "AdaptersConfiguratorMixinTests.test_add_traverser_nondefault_iface": "PASSED",
    "Test_eventonly.test_defaults": "PASSED",
    "TestAssetsConfiguratorMixin.test__override_already_registered": "PASSED",
    "TestAssetsConfiguratorMixin.test__override_not_yet_registered": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_directory_with_absdirectory": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_directory_with_absfile": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_directory_with_file": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_file_with_absdirectory": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_file_with_absfile": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_file_with_directory": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_file_with_missing_abspath": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_file_with_package": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_package_with_absdirectory": "PASSED",
    "TestAssetsConfiguratorMixin.test_override_asset_samename": "PASSED",
    "TestOverrideProvider.test_get_resource_filename_override_returns_value": "PASSED",
    "TestOverrideProvider.test_get_resource_stream_no_overrides": "PASSED",
    "TestOverrideProvider.test_get_resource_stream_override_returns_None": "PASSED",
    "TestOverrideProvider.test_get_resource_stream_override_returns_value": "PASSED",
    "TestOverrideProvider.test_get_resource_string_no_overrides": "PASSED",
    "TestOverrideProvider.test_get_resource_string_override_returns_None": "PASSED",
    "TestOverrideProvider.test_get_resource_string_override_returns_value": "PASSED",
    "TestOverrideProvider.test_has_resource_no_overrides": "PASSED",
    "TestOverrideProvider.test_has_resource_override_returns_None": "PASSED",
    "TestOverrideProvider.test_has_resource_override_returns_True": "PASSED",
    "TestOverrideProvider.test_resource_isdir_no_overrides": "PASSED",
    "TestOverrideProvider.test_resource_isdir_override_returns_False": "PASSED",
    "TestOverrideProvider.test_resource_isdir_override_returns_None": "PASSED",
    "TestOverrideProvider.test_resource_listdir_no_overrides": "PASSED",
    "TestOverrideProvider.test_resource_listdir_override_returns_None": "PASSED",
    "TestOverrideProvider.test_resource_listdir_override_returns_values": "PASSED",
    "TestPackageOverrides.test_class_conforms_to_IPEP302Loader": "PASSED",
    "TestPackageOverrides.test_class_conforms_to_IPackageOverrides": "PASSED",
    "TestPackageOverrides.test_ctor_package_already_has_loader_of_different_type": "PASSED",
    "TestPackageOverrides.test_ctor_package_already_has_loader_of_same_type": "PASSED",
    "TestPackageOverrides.test_ctor_registers_loader_type": "PASSED",
    "TestPackageOverrides.test_ctor_sets_loader": "PASSED",
    "TestPackageOverrides.test_ctor_sets_local_state": "PASSED",
    "TestPackageOverrides.test_filtered_sources": "PASSED",
    "TestPackageOverrides.test_get_code_pkg_has___loader__": "PASSED",
    "TestPackageOverrides.test_get_code_pkg_has_no___loader__": "PASSED",
    "TestPackageOverrides.test_get_data_pkg_has___loader__": "PASSED",
    "TestPackageOverrides.test_get_data_pkg_has_no___loader__": "PASSED",
    "TestPackageOverrides.test_get_filename": "PASSED",
    "TestPackageOverrides.test_get_filename_file_doesnt_exist": "PASSED",
    "TestPackageOverrides.test_get_source_pkg_has___loader__": "PASSED",
    "TestPackageOverrides.test_get_source_pkg_has_no___loader__": "PASSED",
    "TestPackageOverrides.test_get_stream": "PASSED",
    "TestPackageOverrides.test_get_stream_file_doesnt_exist": "PASSED",
    "TestPackageOverrides.test_get_string": "PASSED",
    "TestPackageOverrides.test_get_string_file_doesnt_exist": "PASSED",
    "TestPackageOverrides.test_has_resource": "PASSED",
    "TestPackageOverrides.test_has_resource_file_doesnt_exist": "PASSED",
    "TestPackageOverrides.test_insert_directory": "PASSED",
    "TestPackageOverrides.test_insert_emptystring": "PASSED",
    "TestPackageOverrides.test_insert_file": "PASSED",
    "TestPackageOverrides.test_instance_conforms_to_IPEP302Loader": "PASSED",
    "TestPackageOverrides.test_instance_conforms_to_IPackageOverrides": "PASSED",
    "TestPackageOverrides.test_is_package_pkg_has___loader__": "PASSED",
    "TestPackageOverrides.test_is_package_pkg_has_no___loader__": "PASSED",
    "TestPackageOverrides.test_isdir_doesnt_exist": "PASSED",
    "TestPackageOverrides.test_isdir_false": "PASSED",
    "TestPackageOverrides.test_isdir_true": "PASSED",
    "TestPackageOverrides.test_listdir": "PASSED",
    "TestPackageOverrides.test_listdir_doesnt_exist": "PASSED",
    "TestPackageAssetSource.test_exists": "PASSED",
    "TestPackageAssetSource.test_exists_file_doesnt_exist": "PASSED",
    "TestPackageAssetSource.test_exists_with_prefix": "PASSED",
    "TestPackageAssetSource.test_get_filename_file_doesnt_exist": "PASSED",
    "TestPackageAssetSource.test_get_stream": "PASSED",
    "TestPackageAssetSource.test_get_stream_file_doesnt_exist": "PASSED",
    "TestPackageAssetSource.test_get_stream_with_prefix": "PASSED",
    "TestPackageAssetSource.test_get_string": "PASSED",
    "TestPackageAssetSource.test_get_string_file_doesnt_exist": "PASSED",
    "TestPackageAssetSource.test_get_string_with_prefix": "PASSED",
    "TestPackageAssetSource.test_isdir_doesnt_exist": "PASSED",
    "TestPackageAssetSource.test_isdir_false": "PASSED",
    "TestPackageAssetSource.test_isdir_true": "PASSED",
    "TestPackageAssetSource.test_listdir": "PASSED",
    "TestPackageAssetSource.test_listdir_doesnt_exist": "PASSED",
    "TestFSAssetSource.test_exists": "PASSED",
    "TestFSAssetSource.test_exists_file_doesnt_exist": "PASSED",
    "TestFSAssetSource.test_exists_with_prefix": "PASSED",
    "TestFSAssetSource.test_get_filename": "PASSED",
    "TestFSAssetSource.test_get_filename_file_doesnt_exist": "PASSED",
    "TestFSAssetSource.test_get_filename_with_prefix": "PASSED",
    "TestFSAssetSource.test_get_stream": "PASSED",
    "TestFSAssetSource.test_get_stream_file_doesnt_exist": "PASSED",
    "TestFSAssetSource.test_get_stream_with_prefix": "PASSED",
    "TestFSAssetSource.test_get_string": "PASSED",
    "TestFSAssetSource.test_get_string_file_doesnt_exist": "PASSED",
    "TestFSAssetSource.test_get_string_with_prefix": "PASSED",
    "TestFSAssetSource.test_isdir_doesnt_exist": "PASSED",
    "TestFSAssetSource.test_isdir_false": "PASSED",
    "TestFSAssetSource.test_isdir_true": "PASSED",
    "TestFSAssetSource.test_listdir": "PASSED",
    "TestFSAssetSource.test_listdir_doesnt_exist": "PASSED",
    "TestDirectoryOverride.test_it_match": "PASSED",
    "TestDirectoryOverride.test_it_no_match": "PASSED",
    "TestFileOverride.test_it_match": "PASSED",
    "TestFileOverride.test_it_no_match": "PASSED",
    "TestFactoriesMixin.test_add_request_method_with_None_callable": "PASSED",
    "TestFactoriesMixin.test_add_request_method_with_None_callable_and_no_name": "PASSED",
    "TestFactoriesMixin.test_add_request_method_with_None_callable_conflict": "PASSED",
    "TestFactoriesMixin.test_add_request_method_with_callable": "PASSED",
    "TestFactoriesMixin.test_add_request_method_with_text_type_name": "PASSED",
    "TestFactoriesMixin.test_add_request_method_with_unnamed_callable": "PASSED",
    "TestFactoriesMixin.test_set_multiple_request_methods_conflict": "PASSED",
    "TestFactoriesMixin.test_set_request_factory": "PASSED",
    "TestFactoriesMixin.test_set_request_factory_dottedname": "PASSED",
    "TestFactoriesMixin.test_set_response_factory": "PASSED",
    "TestFactoriesMixin.test_set_response_factory_dottedname": "PASSED",
    "TestFactoriesMixin.test_set_root_factory": "PASSED",
    "TestFactoriesMixin.test_set_root_factory_as_None": "PASSED",
    "TestFactoriesMixin.test_set_root_factory_dottedname": "PASSED",
    "TestFactoriesMixin.test_set_session_factory": "PASSED",
    "TestFactoriesMixin.test_set_session_factory_dottedname": "PASSED",
    "TestDeprecatedFactoriesMixinMethods.test_set_multiple_request_properties": "PASSED",
    "TestDeprecatedFactoriesMixinMethods.test_set_multiple_request_properties_conflict": "PASSED",
    "TestDeprecatedFactoriesMixinMethods.test_set_request_property_with_callable": "PASSED",
    "TestDeprecatedFactoriesMixinMethods.test_set_request_property_with_property": "PASSED",
    "TestDeprecatedFactoriesMixinMethods.test_set_request_property_with_unnamed_callable": "PASSED",
    "TestI18NConfiguratorMixin.test_add_translation_dirs_missing_dir": "PASSED",
    "TestI18NConfiguratorMixin.test_add_translation_dirs_no_specs": "PASSED",
    "TestI18NConfiguratorMixin.test_set_locale_negotiator": "PASSED",
    "TestI18NConfiguratorMixin.test_set_locale_negotiator_dottedname": "PASSED",
    "ConfiguratorTests.test___getattr__matches": "PASSED",
    "ConfiguratorTests.test___getattr__matches_no_action_wrap": "PASSED",
    "ConfiguratorTests.test___getattr__missing_when_directives_dont_exist": "PASSED",
    "ConfiguratorTests.test___getattr__missing_when_directives_exist": "PASSED",
    "ConfiguratorTests.test__fix_registry_adds__lock": "PASSED",
    "ConfiguratorTests.test__fix_registry_adds_clear_view_lookup_cache": "PASSED",
    "ConfiguratorTests.test__fix_registry_has_listeners": "PASSED",
    "ConfiguratorTests.test__fix_registry_notify": "PASSED",
    "ConfiguratorTests.test__fix_registry_queryAdapterOrSelf": "PASSED",
    "ConfiguratorTests.test__fix_registry_registerSelfAdapter": "PASSED",
    "ConfiguratorTests.test_absolute_asset_spec_already_absolute": "PASSED",
    "ConfiguratorTests.test_absolute_asset_spec_notastring": "PASSED",
    "ConfiguratorTests.test_absolute_asset_spec_relative": "PASSED",
    "ConfiguratorTests.test_action_autocommit_with_introspectables": "PASSED",
    "ConfiguratorTests.test_action_autocommit_with_introspectables_introspection_off": "PASSED",
    "ConfiguratorTests.test_action_branching_kw_is_None": "PASSED",
    "ConfiguratorTests.test_action_branching_kw_is_not_None": "PASSED",
    "ConfiguratorTests.test_action_branching_nonautocommit_with_config_info": "PASSED",
    "ConfiguratorTests.test_action_branching_nonautocommit_with_introspectables": "PASSED",
    "ConfiguratorTests.test_action_branching_nonautocommit_without_config_info": "PASSED",
    "ConfiguratorTests.test_action_nonautocommit_with_introspectables_introspection_off": "PASSED",
    "ConfiguratorTests.test_autocommit_no_conflicts": "PASSED",
    "ConfiguratorTests.test_begin": "PASSED",
    "ConfiguratorTests.test_begin_with_request": "PASSED",
    "ConfiguratorTests.test_commit_conflict_resolved_with_include": "PASSED",
    "ConfiguratorTests.test_commit_conflict_resolved_with_two_includes_and_local": "PASSED",
    "ConfiguratorTests.test_commit_conflict_simple": "PASSED",
    "ConfiguratorTests.test_commit_conflict_with_two_includes": "PASSED",
    "ConfiguratorTests.test_conflict_set_forbidden_view": "PASSED",
    "ConfiguratorTests.test_conflict_set_notfound_view": "PASSED",
    "ConfiguratorTests.test_ctor_alternate_renderers": "PASSED",
    "ConfiguratorTests.test_ctor_authentication_policy": "PASSED",
    "ConfiguratorTests.test_ctor_authorization_policy_only": "PASSED",
    "ConfiguratorTests.test_ctor_default_permission": "PASSED",
    "ConfiguratorTests.test_ctor_default_renderers": "PASSED",
    "ConfiguratorTests.test_ctor_default_view_mapper": "PASSED",
    "ConfiguratorTests.test_ctor_default_webob_response_adapter_registered": "PASSED",
    "ConfiguratorTests.test_ctor_exceptionresponse_view_None": "PASSED",
    "ConfiguratorTests.test_ctor_exceptionresponse_view_custom": "PASSED",
    "ConfiguratorTests.test_ctor_httpexception_view_default": "PASSED",
    "ConfiguratorTests.test_ctor_no_root_factory": "PASSED",
    "ConfiguratorTests.test_ctor_noreg_custom_settings": "PASSED",
    "ConfiguratorTests.test_ctor_noreg_debug_logger_non_None": "PASSED",
    "ConfiguratorTests.test_ctor_session_factory": "PASSED",
    "ConfiguratorTests.test_ctor_with_introspection": "PASSED",
    "ConfiguratorTests.test_ctor_with_package_registry": "PASSED",
    "ConfiguratorTests.test_ctor_with_root_factory": "PASSED",
    "ConfiguratorTests.test_end": "PASSED",
    "ConfiguratorTests.test_hook_zca": "PASSED",
    "ConfiguratorTests.test_include_with_dotted_name": "PASSED",
    "ConfiguratorTests.test_include_with_missing_source_file": "PASSED",
    "ConfiguratorTests.test_include_with_module_defaults_to_includeme": "PASSED",
    "ConfiguratorTests.test_include_with_module_defaults_to_includeme_missing": "PASSED",
    "ConfiguratorTests.test_include_with_nested_route_prefix": "PASSED",
    "ConfiguratorTests.test_include_with_python_callable": "PASSED",
    "ConfiguratorTests.test_include_with_route_prefix": "PASSED",
    "ConfiguratorTests.test_introspector_decorator": "PASSED",
    "ConfiguratorTests.test_make_wsgi_app": "PASSED",
    "ConfiguratorTests.test_maybe_dotted_notstring_success": "PASSED",
    "ConfiguratorTests.test_maybe_dotted_string_fail": "PASSED",
    "ConfiguratorTests.test_maybe_dotted_string_success": "PASSED",
    "ConfiguratorTests.test_scan_integration": "PASSED",
    "ConfiguratorTests.test_scan_integration_dottedname_package": "PASSED",
    "ConfiguratorTests.test_scan_integration_with_extra_kw": "PASSED",
    "ConfiguratorTests.test_scan_integration_with_ignore": "PASSED",
    "ConfiguratorTests.test_scan_integration_with_onerror": "PASSED",
    "ConfiguratorTests.test_setup_registry_alternate_renderers": "PASSED",
    "ConfiguratorTests.test_setup_registry_authentication_policy": "PASSED",
    "ConfiguratorTests.test_setup_registry_authentication_policy_dottedname": "PASSED",
    "ConfiguratorTests.test_setup_registry_authorization_policy_dottedname": "PASSED",
    "ConfiguratorTests.test_setup_registry_authorization_policy_only": "PASSED",
    "ConfiguratorTests.test_setup_registry_calls_fix_registry": "PASSED",
    "ConfiguratorTests.test_setup_registry_custom_settings": "PASSED",
    "ConfiguratorTests.test_setup_registry_debug_logger_name": "PASSED",
    "ConfiguratorTests.test_setup_registry_debug_logger_non_None": "PASSED",
    "ConfiguratorTests.test_setup_registry_default_permission": "PASSED",
    "ConfiguratorTests.test_setup_registry_dottedname_root_factory": "PASSED",
    "ConfiguratorTests.test_setup_registry_explicit_notfound_trumps_iexceptionresponse": "PASSED",
    "ConfiguratorTests.test_setup_registry_includes": "PASSED",
    "ConfiguratorTests.test_setup_registry_includes_spaces": "PASSED",
    "ConfiguratorTests.test_setup_registry_locale_negotiator": "PASSED",
    "ConfiguratorTests.test_setup_registry_locale_negotiator_dottedname": "PASSED",
    "ConfiguratorTests.test_setup_registry_no_default_root_factory": "PASSED",
    "ConfiguratorTests.test_setup_registry_registers_default_exceptionresponse_views": "PASSED",
    "ConfiguratorTests.test_setup_registry_registers_default_view_predicates": "PASSED",
    "ConfiguratorTests.test_setup_registry_registers_default_webob_iresponse_adapter": "PASSED",
    "ConfiguratorTests.test_setup_registry_request_factory": "PASSED",
    "ConfiguratorTests.test_setup_registry_request_factory_dottedname": "PASSED",
    "ConfiguratorTests.test_setup_registry_response_factory": "PASSED",
    "ConfiguratorTests.test_setup_registry_tweens": "PASSED",
    "ConfiguratorTests.test_unhook_zca": "PASSED",
    "ConfiguratorTests.test_with_package": "PASSED",
    "ConfiguratorTests.test_with_package_module": "PASSED",
    "ConfiguratorTests.test_with_package_package": "PASSED",
    "TestConfigurator_add_directive.test_directive_persists_across_configurator_creations": "PASSED",
    "TestConfigurator_add_directive.test_extend_action_method_successful": "PASSED",
    "TestConfigurator_add_directive.test_extend_same_name_doesnt_conflict": "PASSED",
    "TestConfigurator__add_predicate.test_factory_as_object": "PASSED",
    "TestActionState.test_action_simple": "PASSED",
    "TestActionState.test_action_with_includepath": "PASSED",
    "TestActionState.test_action_with_includepath_and_info": "PASSED",
    "TestActionState.test_action_with_info": "PASSED",
    "TestActionState.test_action_with_introspectables": "PASSED",
    "TestActionState.test_action_with_order": "PASSED",
    "TestActionState.test_execute_actions_dicts": "PASSED",
    "TestActionState.test_execute_actions_error": "PASSED",
    "TestActionState.test_execute_actions_tuples": "PASSED",
    "TestActionState.test_execute_actions_with_introspectable_no_callable": "PASSED",
    "TestActionState.test_execute_actions_with_introspectables": "PASSED",
    "TestActionState.test_it": "PASSED",
    "TestActionState.test_processSpec": "PASSED",
    "TestActionState.test_reentrant_action": "PASSED",
    "TestActionState.test_reentrant_action_error": "PASSED",
    "TestActionState.test_reentrant_action_without_clear": "PASSED",
    "Test_reentrant_action_functional.test_functional": "PASSED",
    "Test_resolveConflicts.test_it_conflict": "PASSED",
    "Test_resolveConflicts.test_it_success_dicts": "PASSED",
    "Test_resolveConflicts.test_it_success_tuples": "PASSED",
    "Test_resolveConflicts.test_it_with_actions_grouped_by_order": "PASSED",
    "TestGlobalRegistriesIntegration.test_global_registries": "PASSED",
    "TestGlobalRegistriesIntegration.test_global_registries_empty": "PASSED",
    "TestXHRPredicate.test___call___false": "PASSED",
    "TestXHRPredicate.test___call___true": "PASSED",
    "TestXHRPredicate.test_phash": "PASSED",
    "TestXHRPredicate.test_text": "PASSED",
    "TestRequestMethodPredicate.test___call___false": "PASSED",
    "TestRequestMethodPredicate.test___call___true_multi": "PASSED",
    "TestRequestMethodPredicate.test___call___true_single": "PASSED",
    "TestRequestMethodPredicate.test_ctor_get_but_no_head": "PASSED",
    "TestRequestMethodPredicate.test_phash": "PASSED",
    "TestRequestMethodPredicate.test_text": "PASSED",
    "TestPathInfoPredicate.test___call___false": "PASSED",
    "TestPathInfoPredicate.test___call___true": "PASSED",
    "TestPathInfoPredicate.test_ctor_compilefail": "PASSED",
    "TestPathInfoPredicate.test_phash": "PASSED",
    "TestPathInfoPredicate.test_text": "PASSED",
    "TestRequestParamPredicate.test___call___false": "PASSED",
    "TestRequestParamPredicate.test___call___false_multi": "PASSED",
    "TestRequestParamPredicate.test___call___true_exists": "PASSED",
    "TestRequestParamPredicate.test___call___true_multi": "PASSED",
    "TestRequestParamPredicate.test___call___true_withval": "PASSED",
    "TestRequestParamPredicate.test_phash_exists": "PASSED",
    "TestRequestParamPredicate.test_phash_exists_equal_sign": "PASSED",
    "TestRequestParamPredicate.test_phash_withval": "PASSED",
    "TestRequestParamPredicate.test_text_exists": "PASSED",
    "TestRequestParamPredicate.test_text_exists_equal_sign": "PASSED",
    "TestRequestParamPredicate.test_text_multi": "PASSED",
    "TestRequestParamPredicate.test_text_multi_equal_sign": "PASSED",
    "TestRequestParamPredicate.test_text_withval": "PASSED",
    "TestMatchParamPredicate.test___call___false": "PASSED",
    "TestMatchParamPredicate.test___call___matchdict_is_None": "PASSED",
    "TestMatchParamPredicate.test___call___true_multi": "PASSED",
    "TestMatchParamPredicate.test___call___true_single": "PASSED",
    "TestMatchParamPredicate.test_phash": "PASSED",
    "TestMatchParamPredicate.test_text": "PASSED",
    "TestCustomPredicate.test___call___false": "PASSED",
    "TestCustomPredicate.test___call___true": "PASSED",
    "TestCustomPredicate.test_phash": "PASSED",
    "TestCustomPredicate.test_text_func_has___text__": "PASSED",
    "TestCustomPredicate.test_text_func_repr": "PASSED",
    "TestTraversePredicate.test___call__traverse_has_remainder_already": "PASSED",
    "TestTraversePredicate.test___call__traverse_matches": "PASSED",
    "TestTraversePredicate.test___call__traverse_matches_with_highorder_chars": "PASSED",
    "TestTraversePredicate.test_phash": "PASSED",
    "TestTraversePredicate.test_text": "PASSED",
    "Test_CheckCSRFTokenPredicate.test_it_call_val_False": "PASSED",
    "Test_CheckCSRFTokenPredicate.test_it_call_val_True": "PASSED",
    "Test_CheckCSRFTokenPredicate.test_it_call_val_str": "PASSED",
    "Test_CheckCSRFTokenPredicate.test_phash": "PASSED",
    "Test_CheckCSRFTokenPredicate.test_text": "PASSED",
    "TestHeaderPredicate.test___call___false": "PASSED",
    "TestHeaderPredicate.test___call___false_withregex": "PASSED",
    "TestHeaderPredicate.test___call___true_exists": "PASSED",
    "TestHeaderPredicate.test___call___true_withregex": "PASSED",
    "TestHeaderPredicate.test___call___true_withval": "PASSED",
    "TestHeaderPredicate.test_phash_exists": "PASSED",
    "TestHeaderPredicate.test_phash_withregex": "PASSED",
    "TestHeaderPredicate.test_phash_withval": "PASSED",
    "TestHeaderPredicate.test_text_exists": "PASSED",
    "TestHeaderPredicate.test_text_withregex": "PASSED",
    "TestHeaderPredicate.test_text_withval": "PASSED",
    "Test_PhysicalPathPredicate.test_it_call_False": "PASSED",
    "Test_PhysicalPathPredicate.test_it_call_context_has_no_name": "PASSED",
    "Test_PhysicalPathPredicate.test_it_call_val_list_True": "PASSED",
    "Test_PhysicalPathPredicate.test_it_call_val_str_True": "PASSED",
    "Test_PhysicalPathPredicate.test_it_call_val_tuple_True": "PASSED",
    "Test_PhysicalPathPredicate.test_phash": "PASSED",
    "Test_PhysicalPathPredicate.test_text": "PASSED",
    "Test_EffectivePrincipalsPredicate.test_it_call_authentication_policy_doesnt_provide_superset": "PASSED",
    "Test_EffectivePrincipalsPredicate.test_it_call_authentication_policy_provides_superset": "PASSED",
    "Test_EffectivePrincipalsPredicate.test_it_call_authentication_policy_provides_superset_implicit": "PASSED",
    "Test_EffectivePrincipalsPredicate.test_it_call_no_authentication_policy": "PASSED",
    "Test_EffectivePrincipalsPredicate.test_phash": "PASSED",
    "Test_EffectivePrincipalsPredicate.test_text": "PASSED",
    "Test_EffectivePrincipalsPredicate.test_text_noniter": "PASSED",
    "TestRenderingConfiguratorMixin.test_add_default_renderers": "PASSED",
    "TestRenderingConfiguratorMixin.test_add_renderer": "PASSED",
    "TestRenderingConfiguratorMixin.test_add_renderer_dottedname_factory": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_defaults": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_discriminator": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_no_path_no_pattern": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_no_pattern_with_path": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_no_view_with_view_attr": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_no_view_with_view_context": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_no_view_with_view_permission": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_no_view_with_view_renderer": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_accept": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_custom_predicates": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_factory": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_factory_dottedname": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_header": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_path_info": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_path_info_highorder": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_path_info_regex": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_pregenerator": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_request_method": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_request_param": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_route_prefix": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_static": "PASSED",
    "RoutesConfiguratorMixinTests.test_add_route_with_xhr": "PASSED",
    "RoutesConfiguratorMixinTests.test_get_routes_mapper_already_registered": "PASSED",
    "RoutesConfiguratorMixinTests.test_get_routes_mapper_not_yet_registered": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_add_permission": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_authentication_policy_no_authz_policy": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_authentication_policy_no_authz_policy_autocommit": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_authentication_policy_with_authz_policy": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_authentication_policy_with_authz_policy_autocommit": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_authorization_policy_no_authn_policy": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_authorization_policy_no_authn_policy_autocommit": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_authorization_policy_with_authn_policy": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_authorization_policy_with_authn_policy_autocommit": "PASSED",
    "ConfiguratorSecurityMethodsTests.test_set_default_permission": "PASSED",
    "TestSettingsConfiguratorMixin.test__set_settings_as_None": "PASSED",
    "TestSettingsConfiguratorMixin.test__set_settings_as_dictwithvalues": "PASSED",
    "TestSettingsConfiguratorMixin.test_add_settings_settings_None": "PASSED",
    "TestSettingsConfiguratorMixin.test_add_settings_settings_already_registered": "PASSED",
    "TestSettingsConfiguratorMixin.test_add_settings_settings_not_yet_registered": "PASSED",
    "TestSettingsConfiguratorMixin.test_get_settings_nosettings": "PASSED",
    "TestSettingsConfiguratorMixin.test_get_settings_withsettings": "PASSED",
    "TestSettings.test_debug_all": "PASSED",
    "TestSettings.test_debug_authorization": "PASSED",
    "TestSettings.test_debug_notfound": "PASSED",
    "TestSettings.test_debug_routematch": "PASSED",
    "TestSettings.test_debug_templates": "PASSED",
    "TestSettings.test_default_locale_name": "PASSED",
    "TestSettings.test_getattr_fail": "PASSED",
    "TestSettings.test_getattr_raises_attribute_error": "PASSED",
    "TestSettings.test_getattr_success": "PASSED",
    "TestSettings.test_noargs": "PASSED",
    "TestSettings.test_originals_kept": "PASSED",
    "TestSettings.test_prevent_cachebust": "PASSED",
    "TestSettings.test_prevent_http_cache": "PASSED",
    "TestSettings.test_reload_all": "PASSED",
    "TestSettings.test_reload_assets": "PASSED",
    "TestSettings.test_reload_resources": "PASSED",
    "TestSettings.test_reload_templates": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_add_renderer": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_add_renderer_explicitrenderer": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_add_renderer_twice": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_add_subscriber_defaults": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_add_subscriber_dottedname": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_add_subscriber_multiple": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_add_subscriber_single": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_add_template": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_resources": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_securitypolicy": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_securitypolicy_forget_result": "PASSED",
    "TestingConfiguratorMixinTests.test_testing_securitypolicy_remember_result": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_dottedname": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_instance": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_name_ingress": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_name_main": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_over_ingress": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_over_ingress_iterable": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_under_main": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_under_main_iterable": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tween_unsuitable": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tweens_conflict": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tweens_names_distinct": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tweens_names_with_over_nonstringoriter": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tweens_names_with_under_nonstringoriter": "PASSED",
    "TestTweensConfiguratorMixin.test_add_tweens_names_with_underover": "PASSED",
    "TestTweens.test___call___explicit": "PASSED",
    "TestTweens.test___call___implicit": "PASSED",
    "TestTweens.test_add_explicit": "PASSED",
    "TestTweens.test_add_implicit": "PASSED",
    "TestTweens.test_implicit_ordering_1": "PASSED",
    "TestTweens.test_implicit_ordering_2": "PASSED",
    "TestTweens.test_implicit_ordering_3": "PASSED",
    "TestTweens.test_implicit_ordering_4": "PASSED",
    "TestTweens.test_implicit_ordering_5": "PASSED",
    "TestTweens.test_implicit_ordering_conflict_direct": "PASSED",
    "TestTweens.test_implicit_ordering_conflict_indirect": "PASSED",
    "TestTweens.test_implicit_ordering_missing_over_and_under_partials": "PASSED",
    "TestTweens.test_implicit_ordering_missing_over_partial": "PASSED",
    "TestTweens.test_implicit_ordering_missing_over_partial_with_fallback": "PASSED",
    "TestTweens.test_implicit_ordering_missing_under_partial": "PASSED",
    "TestTweens.test_implicit_ordering_missing_under_partial_with_fallback": "PASSED",
    "TestTweens.test_implicit_ordering_with_missing_fallbacks": "PASSED",
    "TestTweens.test_implicit_ordering_with_multiple_matching_fallbacks": "PASSED",
    "TestTweens.test_implicit_ordering_with_partial_fallbacks": "PASSED",
    "TestPredicateList.test_custom_predicates_can_affect_traversal": "PASSED",
    "TestPredicateList.test_different_custom_predicates_with_same_hash": "PASSED",
    "TestPredicateList.test_match_param_from_dict": "PASSED",
    "TestPredicateList.test_match_param_from_dict_fails": "PASSED",
    "TestPredicateList.test_match_param_from_string": "PASSED",
    "TestPredicateList.test_match_param_from_string_fails": "PASSED",
    "TestPredicateList.test_notted": "PASSED",
    "TestPredicateList.test_ordering_importance_and_number": "PASSED",
    "TestPredicateList.test_ordering_importance_of_predicates": "PASSED",
    "TestPredicateList.test_ordering_number_of_predicates": "PASSED",
    "TestPredicateList.test_ordering_xhr_and_request_method_trump_only_containment": "PASSED",
    "TestPredicateList.test_predicate_text_is_correct": "PASSED",
    "TestPredicateList.test_request_method_ordering_hashes_same": "PASSED",
    "TestPredicateList.test_request_method_sequence": "PASSED",
    "TestPredicateList.test_traverse_has_remainder_already": "PASSED",
    "TestPredicateList.test_traverse_matches": "PASSED",
    "TestPredicateList.test_traverse_matches_with_highorder_chars": "PASSED",
    "TestPredicateList.test_unknown_predicate": "PASSED",
    "Test_takes_one_arg.test_function_annotations": "PASSED",
    "Test_takes_one_arg.test_function_defaultargs_firstname_not_request": "PASSED",
    "Test_takes_one_arg.test_function_defaultargs_firstname_request": "PASSED",
    "Test_takes_one_arg.test_function_noargs": "PASSED",
    "Test_takes_one_arg.test_function_onearg_named_request": "PASSED",
    "Test_takes_one_arg.test_function_onearg_named_somethingelse": "PASSED",
    "Test_takes_one_arg.test_function_toomanyargs": "PASSED",
    "Test_takes_one_arg.test_function_with_attr_false": "PASSED",
    "Test_takes_one_arg.test_function_with_attr_true": "PASSED",
    "Test_takes_one_arg.test_instance_defaultargs_firstname_not_request": "PASSED",
    "Test_takes_one_arg.test_instance_defaultargs_firstname_request": "PASSED",
    "Test_takes_one_arg.test_instance_defaultargs_onearg_named_request": "PASSED",
    "Test_takes_one_arg.test_instance_defaultargs_onearg_named_somethingelse": "PASSED",
    "Test_takes_one_arg.test_instance_nocall": "PASSED",
    "Test_takes_one_arg.test_instance_toomanyargs": "PASSED",
    "Test_takes_one_arg.test_method_onearg_named_request": "PASSED",
    "Test_takes_one_arg.test_newstyle_class_init_defaultargs_firstname_not_request": "PASSED",
    "Test_takes_one_arg.test_newstyle_class_init_defaultargs_firstname_request": "PASSED",
    "Test_takes_one_arg.test_newstyle_class_init_firstname_request_with_secondname": "PASSED",
    "Test_takes_one_arg.test_newstyle_class_init_noargs": "PASSED",
    "Test_takes_one_arg.test_newstyle_class_init_onearg_named_somethingelse": "PASSED",
    "Test_takes_one_arg.test_oldstyle_class_init_defaultargs_firstname_not_request": "PASSED",
    "Test_takes_one_arg.test_oldstyle_class_init_defaultargs_firstname_request": "PASSED",
    "Test_takes_one_arg.test_oldstyle_class_init_noargs": "PASSED",
    "Test_takes_one_arg.test_oldstyle_class_init_onearg_named_request": "PASSED",
    "Test_takes_one_arg.test_oldstyle_class_init_onearg_named_somethingelse": "PASSED",
    "Test_takes_one_arg.test_oldstyle_class_init_toomanyargs": "PASSED",
    "Test_takes_one_arg.test_oldstyle_class_no_init": "PASSED",
    "Test_takes_one_arg.test_requestonly_newstyle_class_init_onearg_named_request": "PASSED",
    "Test_takes_one_arg.test_requestonly_newstyle_class_init_toomanyargs": "PASSED",
    "Test_takes_one_arg.test_requestonly_newstyle_class_no_init": "PASSED",
    "TestNotted.test_it_with_phash_val": "PASSED",
    "TestNotted.test_it_without_phash_val": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_allows_other_predicates": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_disallows_context": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_disallows_for_": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_disallows_http_cache": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_disallows_name": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_disallows_permission": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_no_view_argument": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_with_renderer": "PASSED",
    "TestViewsConfigurationMixin.test_add_forbidden_view_with_view_defaults": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_allows_other_predicates": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_append_slash": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_append_slash_custom_response": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_disallows_context": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_disallows_for_": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_disallows_http_cache": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_disallows_name": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_disallows_permission": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_no_view_argument": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_with_renderer": "PASSED",
    "TestViewsConfigurationMixin.test_add_notfound_view_with_view_defaults": "PASSED",
    "TestViewsConfigurationMixin.test_add_static_view_absolute": "PASSED",
    "TestViewsConfigurationMixin.test_add_static_view_here_no_utility_registered": "PASSED",
    "TestViewsConfigurationMixin.test_add_static_view_package_relative": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_as_instance": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_as_instance_requestonly": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_as_instancemethod": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_as_instancemethod_requestonly": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_as_oldstyle_class": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_as_oldstyle_class_requestonly": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_class_method_no_attr": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_context_as_class": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_context_as_dottedname": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_context_as_iface": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_context_trumps_for": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_custom_more_preds_first_bests_fewer_preds_last": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_custom_predicate_bests_standard_predicate": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_default_phash_overrides_default_phash": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_default_phash_overrides_no_phash": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exc_default_phash_overrides_default_phash": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exc_default_phash_overrides_no_phash": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exc_multiview_replaces_existing_securedview": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exc_multiview_replaces_existing_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exc_multiview_replaces_multiview": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exc_mulview_replaces_existing_view_with___accept__": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exc_same_phash_overrides_existing_single_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exc_with_accept_multiview_replaces_existing_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_exception_register_secured_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_for__as_dottedname": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_for_as_class": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_for_as_iface": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_mixed_case_replaces_existing_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_multiview___discriminator__": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_multiview_call_ordering": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_multiview_context_superclass_then_subclass": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_multiview_exception_superclass_then_subclass": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_multiview_replaces_existing_securedview": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_multiview_replaces_existing_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_multiview_replaces_existing_view_with___accept__": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_multiview_replaces_multiview": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_register_secured_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_same_phash_overrides_existing_single_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_same_predicates": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_view_callable_None_no_renderer": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_view_callable_None_with_renderer": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_view_callable_dottedname": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_accept_match": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_accept_multiview_replaces_existing_view": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_accept_nomatch": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_containment_dottedname": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_containment_false": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_containment_true": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_custom_predicates_match": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_custom_predicates_nomatch": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_decorator": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_decorator_tuple": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_default_permission_no_explicit_permission": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_default_renderer": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_function_callable": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_function_callable_requestonly": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_header_badregex": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_header_noval_match": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_header_noval_nomatch": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_header_val_match": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_header_val_missing": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_header_val_nomatch": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_http_cache": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_mapper": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_name": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_name_unicode": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_no_default_permission_no_explicit_permission": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_nonexistant_route_name": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_path_info_badregex": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_path_info_match": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_path_info_nomatch": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_permission": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_method_false": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_method_get_implies_head": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_method_sequence_conflict": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_method_sequence_false": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_method_sequence_true": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_method_true": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_param_noval_false": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_param_noval_true": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_param_val_false": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_param_val_true": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_type": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_type_and_route_name": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_type_as_iface": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_request_type_as_noniface": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_route_name": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_route_name_exception": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_tmpl_renderer_factory_introspector_missing": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_tmpl_renderer_factory_no_renderer_factory": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_tmpl_renderer_factory_with_renderer_factory": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_view_config_and_view_defaults_conflicts": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_view_config_and_view_defaults_doesnt_conflict": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_view_defaults": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_view_defaults_viewname_is_dottedname_kwarg": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_view_defaults_viewname_is_dottedname_nonkwarg": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_xhr_false": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_with_xhr_true": "PASSED",
    "TestViewsConfigurationMixin.test_add_view_wrapped_view_is_decorated": "PASSED",
    "TestViewsConfigurationMixin.test_add_views_with_accept_multiview_replaces_existing": "PASSED",
    "TestViewsConfigurationMixin.test_derive_view_dottedname": "PASSED",
    "TestViewsConfigurationMixin.test_derive_view_function": "PASSED",
    "TestViewsConfigurationMixin.test_derive_view_with_default_renderer_no_explicit_renderer": "PASSED",
    "TestViewsConfigurationMixin.test_derive_view_with_default_renderer_with_explicit_renderer": "PASSED",
    "TestViewsConfigurationMixin.test_set_view_mapper": "PASSED",
    "TestViewsConfigurationMixin.test_set_view_mapper_dottedname": "PASSED",
    "TestViewsConfigurationMixin.test_view_with_most_specific_predicate": "PASSED",
    "TestViewsConfigurationMixin.test_view_with_most_specific_predicate_with_mismatch": "PASSED",
    "Test_requestonly.test_defaults": "PASSED",
    "Test_requestonly.test_otherattr": "PASSED",
    "Test_isexception.test_is_IException": "PASSED",
    "Test_isexception.test_is_IException_subinterface": "PASSED",
    "Test_isexception.test_is_exception_class": "PASSED",
    "Test_isexception.test_is_exception_instance": "PASSED",
    "TestMultiView.test___call__": "PASSED",
    "TestMultiView.test___call__intermediate_not_found": "PASSED",
    "TestMultiView.test___call__raise_not_found_isnt_interpreted_as_pred_mismatch": "PASSED",
    "TestMultiView.test___call_permissive_has_call_permissive": "PASSED",
    "TestMultiView.test___call_permissive_has_no_call_permissive": "PASSED",
    "TestMultiView.test__call__not_found": "PASSED",
    "TestMultiView.test__call__with_accept_match": "PASSED",
    "TestMultiView.test__call__with_accept_miss": "PASSED",
    "TestMultiView.test__call_permissive__not_found": "PASSED",
    "TestMultiView.test_add": "PASSED",
    "TestMultiView.test_add_with_phash": "PASSED",
    "TestMultiView.test_add_with_phash_override_accept": "PASSED",
    "TestMultiView.test_add_with_phash_override_accept2": "PASSED",
    "TestMultiView.test_class_implements_ISecuredView": "PASSED",
    "TestMultiView.test_get_views": "PASSED",
    "TestMultiView.test_get_views_best_match_returns_None": "PASSED",
    "TestMultiView.test_get_views_no_self_accepts": "PASSED",
    "TestMultiView.test_get_views_request_has_no_accept": "PASSED",
    "TestMultiView.test_instance_implements_ISecuredView": "PASSED",
    "TestMultiView.test_match_not_found": "PASSED",
    "TestMultiView.test_match_predicate_fails": "PASSED",
    "TestMultiView.test_match_predicate_succeeds": "PASSED",
    "TestMultiView.test_multiple_with_functions_as_views": "PASSED",
    "TestMultiView.test_permitted": "PASSED",
    "TestMultiView.test_permitted_no_match_with__permitted__": "PASSED",
    "TestMultiView.test_permitted_no_views": "PASSED",
    "TestDefaultViewMapper.test__view_as_function_with_attr": "PASSED",
    "TestDefaultViewMapper.test_view_as_function_context_and_request": "PASSED",
    "TestDefaultViewMapper.test_view_as_function_requestonly": "PASSED",
    "TestDefaultViewMapper.test_view_as_function_requestonly_with_attr": "PASSED",
    "TestDefaultViewMapper.test_view_as_instance_context_and_request": "PASSED",
    "TestDefaultViewMapper.test_view_as_instance_context_and_request_and_attr": "PASSED",
    "TestDefaultViewMapper.test_view_as_instance_requestonly": "PASSED",
    "TestDefaultViewMapper.test_view_as_instance_requestonly_with_attr": "PASSED",
    "TestDefaultViewMapper.test_view_as_newstyle_class_context_and_request": "PASSED",
    "TestDefaultViewMapper.test_view_as_newstyle_class_context_and_request_with_attr": "PASSED",
    "TestDefaultViewMapper.test_view_as_newstyle_class_requestonly": "PASSED",
    "TestDefaultViewMapper.test_view_as_newstyle_class_requestonly_with_attr": "PASSED",
    "TestDefaultViewMapper.test_view_as_oldstyle_class_context_and_request": "PASSED",
    "TestDefaultViewMapper.test_view_as_oldstyle_class_context_and_request_with_attr": "PASSED",
    "TestDefaultViewMapper.test_view_as_oldstyle_class_requestonly": "PASSED",
    "TestDefaultViewMapper.test_view_as_oldstyle_class_requestonly_with_attr": "PASSED",
    "Test_preserve_view_attrs.test_it_different": "PASSED",
    "Test_preserve_view_attrs.test_it_different_with_existing_original_view": "PASSED",
    "Test_preserve_view_attrs.test_it_same": "PASSED",
    "Test_preserve_view_attrs.test_it_view_is_None": "PASSED",
    "TestStaticURLInfo.test_add_already_exists": "PASSED",
    "TestStaticURLInfo.test_add_cachebust_prevented": "PASSED",
    "TestStaticURLInfo.test_add_cachebuster": "PASSED",
    "TestStaticURLInfo.test_add_cachebuster_abspath": "PASSED",
    "TestStaticURLInfo.test_add_cachebuster_for_more_specific_path": "PASSED",
    "TestStaticURLInfo.test_add_cachebuster_overwrite": "PASSED",
    "TestStaticURLInfo.test_add_cachebuster_overwrite_explicit": "PASSED",
    "TestStaticURLInfo.test_add_package_root": "PASSED",
    "TestStaticURLInfo.test_add_url_noendslash": "PASSED",
    "TestStaticURLInfo.test_add_url_noscheme": "PASSED",
    "TestStaticURLInfo.test_add_url_withendslash": "PASSED",
    "TestStaticURLInfo.test_add_viewname": "PASSED",
    "TestStaticURLInfo.test_add_viewname_with_context": "PASSED",
    "TestStaticURLInfo.test_add_viewname_with_for_": "PASSED",
    "TestStaticURLInfo.test_add_viewname_with_permission": "PASSED",
    "TestStaticURLInfo.test_add_viewname_with_renderer": "PASSED",
    "TestStaticURLInfo.test_add_viewname_with_route_prefix": "PASSED",
    "TestStaticURLInfo.test_generate_missing": "PASSED",
    "TestStaticURLInfo.test_generate_quoting": "PASSED",
    "TestStaticURLInfo.test_generate_registration_miss": "PASSED",
    "TestStaticURLInfo.test_generate_route_url": "PASSED",
    "TestStaticURLInfo.test_generate_slash_in_name1": "PASSED",
    "TestStaticURLInfo.test_generate_slash_in_name2": "PASSED",
    "TestStaticURLInfo.test_generate_url_cachebust": "PASSED",
    "TestStaticURLInfo.test_generate_url_cachebust_abspath": "PASSED",
    "TestStaticURLInfo.test_generate_url_cachebust_nomatch": "PASSED",
    "TestStaticURLInfo.test_generate_url_quoted_remote": "PASSED",
    "TestStaticURLInfo.test_generate_url_unquoted_local": "PASSED",
    "TestStaticURLInfo.test_generate_url_with_custom_anchor": "PASSED",
    "TestStaticURLInfo.test_generate_url_with_custom_query": "PASSED",
    "TestStaticURLInfo.test_verifyClass": "PASSED",
    "TestStaticURLInfo.test_verifyObject": "PASSED",
    "Test_view_description.test_with_text": "PASSED",
    "Test_logging_file_config.test_it": "PASSED",
    "TestParseVars.test_parse_vars_bad": "PASSED",
    "TestParseVars.test_parse_vars_good": "PASSED",
    "TestPCreateCommand.test_confirm_override_conflicting_name": "PASSED",
    "TestPCreateCommand.test_force_override_conflicting_name": "PASSED",
    "TestPCreateCommand.test_force_override_site_name": "PASSED",
    "TestPCreateCommand.test_known_scaffold_absolute_path": "PASSED",
    "TestPCreateCommand.test_known_scaffold_multiple_rendered": "PASSED",
    "TestPCreateCommand.test_known_scaffold_single_rendered": "PASSED",
    "TestPCreateCommand.test_known_scaffold_with_path_as_project_target_rendered": "PASSED",
    "TestPCreateCommand.test_no_project_name": "PASSED",
    "TestPCreateCommand.test_run_no_scaffold_name": "PASSED",
    "TestPCreateCommand.test_run_no_scaffold_no_args": "PASSED",
    "TestPCreateCommand.test_run_show_scaffolds_exist": "PASSED",
    "TestPCreateCommand.test_run_show_scaffolds_none_exist": "PASSED",
    "TestPCreateCommand.test_scaffold_with_dev_pyramid_long_version": "PASSED",
    "TestPCreateCommand.test_scaffold_with_dev_pyramid_version": "PASSED",
    "TestPCreateCommand.test_scaffold_with_hyphen_in_project_name": "PASSED",
    "TestPCreateCommand.test_scaffold_with_prod_pyramid_long_version": "PASSED",
    "TestPCreateCommand.test_scaffold_with_prod_pyramid_unparsable_version": "PASSED",
    "TestPCreateCommand.test_scaffold_with_prod_pyramid_version": "PASSED",
    "TestPCreateCommand.test_unknown_scaffold_name": "PASSED",
    "Test_main.test_it": "PASSED",
    "TestPDistReportCommand.test_no_dists": "PASSED",
    "TestPDistReportCommand.test_with_dists": "PASSED",
    "TestPRequestCommand.test_command_has_bad_config_header": "PASSED",
    "TestPRequestCommand.test_command_method_configures_logging": "PASSED",
    "TestPRequestCommand.test_command_not_enough_args": "PASSED",
    "TestPRequestCommand.test_command_response_has_no_charset": "PASSED",
    "TestPRoutesCommand.test__get_mapper": "PASSED",
    "TestPRoutesCommand.test_bad_args": "PASSED",
    "TestPRoutesCommand.test_bad_format": "PASSED",
    "TestPRoutesCommand.test_good_args": "PASSED",
    "TestPRoutesCommand.test_good_format": "PASSED",
    "TestPRoutesCommand.test_no_mapper": "PASSED",
    "TestPRoutesCommand.test_no_routes": "PASSED",
    "TestPRoutesCommand.test_route_as_wsgiapp": "PASSED",
    "TestPRoutesCommand.test_route_no_view": "PASSED",
    "TestPRoutesCommand.test_route_with_no_slash_prefix": "PASSED",
    "TestPRoutesCommand.test_single_route_multiview_registered": "PASSED",
    "TestPRoutesCommand.test_single_route_no_route_registered": "PASSED",
    "TestPRoutesCommand.test_single_route_no_views_registered": "PASSED",
    "TestPRoutesCommand.test_single_route_one_view_registered_with_factory": "PASSED",
    "TestPRoutesCommand.test_static_routes_included_in_list": "PASSED",
    "TestPServeCommand.test_get_options_no_command": "PASSED",
    "TestPServeCommand.test_get_options_with_command": "PASSED",
    "TestPServeCommand.test_parse_vars_bad": "PASSED",
    "TestPServeCommand.test_parse_vars_good": "PASSED",
    "TestPServeCommand.test_record_pid_not_verbose": "PASSED",
    "TestPServeCommand.test_record_pid_verbose": "PASSED",
    "TestPServeCommand.test_remove_pid_current_pid_is_not_pid_in_file": "PASSED",
    "TestPServeCommand.test_remove_pid_current_pid_is_not_written_pid": "PASSED",
    "TestPServeCommand.test_remove_pid_file_not_verbose": "PASSED",
    "TestPServeCommand.test_remove_pid_file_stale_pid_write_exception": "PASSED",
    "TestPServeCommand.test_remove_pid_file_unlink_exception": "PASSED",
    "TestPServeCommand.test_remove_pid_file_verbose": "PASSED",
    "TestPServeCommand.test_remove_pid_no_pid_file": "PASSED",
    "TestPServeCommand.test_remove_pid_not_a_number": "PASSED",
    "TestPServeCommand.test_run_no_args": "PASSED",
    "TestPServeCommand.test_run_stop_daemon_bad_pid_file": "PASSED",
    "TestPServeCommand.test_run_stop_daemon_invalid_pid_in_file": "PASSED",
    "TestPServeCommand.test_run_stop_daemon_no_such_pid_file": "PASSED",
    "Test_read_pidfile.test_read_pidfile": "PASSED",
    "Test_read_pidfile.test_read_pidfile_no_pid_file": "PASSED",
    "Test_read_pidfile.test_read_pidfile_not_a_number": "PASSED",
    "TestLazyWriter.test_flush": "PASSED",
    "TestLazyWriter.test_open": "PASSED",
    "TestLazyWriter.test_write": "PASSED",
    "TestLazyWriter.test_writeline": "PASSED",
    "Test__methodwrapper.test___call__fail": "PASSED",
    "Test__methodwrapper.test___call__succeed": "PASSED",
    "TestPShellCommand.test_command_custom_section_override": "PASSED",
    "TestPShellCommand.test_command_default_shell_option": "PASSED",
    "TestPShellCommand.test_command_errors_with_unknown_shell": "PASSED",
    "TestPShellCommand.test_command_loads_check_variable_override_order": "PASSED",
    "TestPShellCommand.test_command_loads_custom_items": "PASSED",
    "TestPShellCommand.test_command_loads_default_shell": "PASSED",
    "TestPShellCommand.test_command_loads_ipython": "PASSED",
    "TestPShellCommand.test_command_loads_pythonstartup": "PASSED",
    "TestPShellCommand.test_command_loads_setup_from_options": "PASSED",
    "TestPShellCommand.test_command_setup": "PASSED",
    "TestPShellCommand.test_list_shells": "PASSED",
    "TestPShellCommand.test_shell_entry_points": "PASSED",
    "TestPShellCommand.test_shell_ordering": "PASSED",
    "TestPShellCommand.test_shell_override": "PASSED",
    "Test_python_shell_runner.test_it": "PASSED",
    "TestPTweensCommand.test__get_tweens": "PASSED",
    "TestPTweensCommand.test_command_implicit_and_explicit_tweens": "PASSED",
    "TestPTweensCommand.test_command_implicit_tweens_only": "PASSED",
    "TestPTweensCommand.test_command_no_tweens": "PASSED",
    "TestPViewsCommand.test__find_multi_routes_all_match": "PASSED",
    "TestPViewsCommand.test__find_multi_routes_none_match": "PASSED",
    "TestPViewsCommand.test__find_multi_routes_some_match": "PASSED",
    "TestPViewsCommand.test__find_view_no_match": "PASSED",
    "TestPViewsCommand.test__find_view_no_match_multiview_registered": "PASSED",
    "TestPViewsCommand.test__find_view_route_multiview": "PASSED",
    "TestPViewsCommand.test__find_view_route_multiview_no_view_registered": "PASSED",
    "TestPViewsCommand.test__find_view_route_no_multiview": "PASSED",
    "TestPViewsCommand.test__find_view_traversal": "PASSED",
    "TestPViewsCommand.test__find_view_traversal_multiview": "PASSED",
    "TestPViewsCommand.test_views_command_multi_view_nested": "PASSED",
    "TestPViewsCommand.test_views_command_multiview": "PASSED",
    "TestPViewsCommand.test_views_command_multiview_with_permission": "PASSED",
    "TestPViewsCommand.test_views_command_multiview_with_predicates": "PASSED",
    "TestPViewsCommand.test_views_command_not_found": "PASSED",
    "TestPViewsCommand.test_views_command_not_found_url_starts_without_slash": "PASSED",
    "TestPViewsCommand.test_views_command_single_view_route": "PASSED",
    "TestPViewsCommand.test_views_command_single_view_route_with_route_predicates": "PASSED",
    "TestPViewsCommand.test_views_command_single_view_traversal": "PASSED",
    "TestPViewsCommand.test_views_command_single_view_traversal_with_permission": "PASSED",
    "TestPViewsCommand.test_views_command_single_view_traversal_with_predicates": "PASSED",
    "TestDeriveView.test_as_instance_requestonly": "FAILED",
    "TestDeriveView.test_function_returns_non_adaptable": "FAILED",
    "TestDeriveView.test_function_returns_non_adaptable_dict": "FAILED",
    "TestDeriveView.test_instance_returns_non_adaptable": "FAILED",
    "TestDeriveView.test_requestonly_default_method_returns_non_adaptable": "FAILED",
    "TestDeriveView.test_requestonly_nondefault_method_returns_non_adaptable": "FAILED",
    "AdaptersConfiguratorMixinTests.test_add_resource_url_adapter_dotted_names": "FAILED",
    "AdaptersConfiguratorMixinTests.test_add_resource_url_adapter_introspectables": "FAILED",
    "AdaptersConfiguratorMixinTests.test_add_traverser_dotted_names": "FAILED",
    "TestAssetsConfiguratorMixin.test_override_asset_directory_with_directory": "FAILED",
    "TestAssetsConfiguratorMixin.test_override_asset_directory_with_package": "FAILED",
    "TestAssetsConfiguratorMixin.test_override_asset_file_with_file": "FAILED",
    "TestAssetsConfiguratorMixin.test_override_asset_package_with_directory": "FAILED",
    "TestAssetsConfiguratorMixin.test_override_asset_package_with_package": "FAILED",
    "TestOverrideProvider.test_get_resource_filename_no_overrides": "FAILED",
    "TestOverrideProvider.test_get_resource_filename_override_returns_None": "FAILED",
    "TestPackageAssetSource.test_get_filename": "FAILED",
    "TestPackageAssetSource.test_get_filename_with_prefix": "FAILED",
    "TestI18NConfiguratorMixin.test_add_translation_dirs_abspath": "FAILED",
    "TestI18NConfiguratorMixin.test_add_translation_dirs_asset_spec": "FAILED",
    "TestI18NConfiguratorMixin.test_add_translation_dirs_asset_spec_existing_translation_dirs": "FAILED",
    "TestI18NConfiguratorMixin.test_add_translation_dirs_multiple_specs": "FAILED",
    "TestI18NConfiguratorMixin.test_add_translation_dirs_multiple_specs_multiple_calls": "FAILED",
    "ConfiguratorTests.test_ctor_no_registry": "FAILED",
    "ConfiguratorTests.test_ctor_noreg_debug_logger_None_default": "FAILED",
    "ConfiguratorTests.test_include_constant_root_package": "FAILED",
    "ConfiguratorTests.test_scan_integration_conflict": "FAILED",
    "ConfiguratorTests.test_setup_registry_debug_logger_None_default": "FAILED",
    "TestConfigurator_add_directive.test_add_directive_with_custom_callable": "FAILED",
    "TestConfigurator_add_directive.test_add_directive_with_partial": "FAILED",
    "TestConfigurator_add_directive.test_extend_with_dotted_name": "FAILED",
    "TestConfigurator_add_directive.test_extend_with_python_callable": "FAILED",
    "TestConfigurator__add_predicate.test_factory_as_dotted_name": "FAILED",
    "TestViewsConfigurationMixin.test_add_static_view_package_here_relative": "FAILED",
    "TestViewsConfigurationMixin.test_add_view_with_template_renderer": "FAILED",
    "TestViewsConfigurationMixin.test_add_view_with_template_renderer_no_callable": "FAILED",
    "TestStaticURLInfo.test_generate_url_cachebust_with_overrides": "FAILED",
    "Test_view_description.test_without_text": "FAILED",
    "TestPRequestCommand.test_command_display_headers": "FAILED",
    "TestPRequestCommand.test_command_has_content_type_header_var": "FAILED",
    "TestPRequestCommand.test_command_has_good_header_var": "FAILED",
    "TestPRequestCommand.test_command_has_multiple_header_vars": "FAILED",
    "TestPRequestCommand.test_command_method_get": "FAILED",
    "TestPRequestCommand.test_command_method_options": "FAILED",
    "TestPRequestCommand.test_command_method_patch": "FAILED",
    "TestPRequestCommand.test_command_method_post": "FAILED",
    "TestPRequestCommand.test_command_method_propfind": "FAILED",
    "TestPRequestCommand.test_command_method_put": "FAILED",
    "TestPRequestCommand.test_command_path_doesnt_start_with_slash": "FAILED",
    "TestPRequestCommand.test_command_two_args": "FAILED",
    "TestPRequestCommand.test_command_w_basic_auth": "FAILED",
    "TestPRequestCommand.test_command_with_query_string": "FAILED",
    "TestPRoutesCommand.test_config_format_ini_commas": "FAILED",
    "TestPRoutesCommand.test_config_format_ini_newlines": "FAILED",
    "TestPRoutesCommand.test_config_format_ini_spaces": "FAILED",
    "TestPRoutesCommand.test_one_route_all_methods_view_only_post": "FAILED",
    "TestPRoutesCommand.test_one_route_only_post_view_all_methods": "FAILED",
    "TestPRoutesCommand.test_one_route_only_post_view_post_and_get": "FAILED",
    "TestPRoutesCommand.test_one_route_with_long_name_one_view_registered": "FAILED",
    "TestPRoutesCommand.test_route_is_get_view_request_method_not_post": "FAILED",
    "TestPRoutesCommand.test_route_request_method_mismatch": "FAILED",
    "TestPRoutesCommand.test_route_static_views": "FAILED",
    "TestPRoutesCommand.test_single_route_one_view_registered": "FAILED",
    "TestPRoutesCommand.test_view_glob": "FAILED",
    "TestPRoutesCommand.test_view_request_method_not_post": "FAILED",
    "TestPViewsCommand.test_views_command_single_view_function_traversal": "FAILED"
}
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 1e161177b..3f6a9080d 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -80,7 +80,7 @@ import pyramid.viewderivers
 
 from pyramid.viewderivers import (
     INGRESS,
-    MAPPED_VIEW,
+    VIEW,
     preserve_view_attrs,
     view_description,
     requestonly,
@@ -1115,9 +1115,12 @@ class ViewsConfiguratorMixin(object):
         ``under`` means closer to the user-defined :term:`view callable`,
         and ``over`` means closer to view pipeline ingress.
 
-        Specifying neither ``under`` nor ``over`` is equivalent to specifying
-        ``over='rendered_view'`` and ``under='decorated_view'``, placing the
-        deriver somewhere between the ``decorated_view`` and ``rendered_view``
+        The default value for ``over`` is ``rendered_view`` and ``under`` is
+        ``decorated_view``. This places the deriver somewhere between the two
+        in the view pipeline. If the deriver should be placed elsewhere in the
+        pipeline, such as above ``decorated_view``, then you MUST also specify
+        ``under`` to something earlier in the order, or a
+        ``CyclicDependencyError`` will be raised when trying to sort the
         derivers.
 
         See :ref:`view_derivers` for more information.
@@ -1128,33 +1131,30 @@ class ViewsConfiguratorMixin(object):
         if name is None:
             name = deriver.__name__
 
-        if name in (INGRESS,):
+        if name in (INGRESS, VIEW):
             raise ConfigurationError('%s is a reserved view deriver name'
                                      % name)
 
-        if under is None and over is None:
+        if under is None:
             under = 'decorated_view'
+
+        if over is None:
             over = 'rendered_view'
 
-        if over is None and name != MAPPED_VIEW:
-            raise ConfigurationError('must specify an "over" constraint for '
-                                     'the %s view deriver' % name)
-        elif over is not None:
-            over = as_sorted_tuple(over)
+        over = as_sorted_tuple(over)
+        under = as_sorted_tuple(under)
 
-        if under is None:
-            raise ConfigurationError('must specify an "under" constraint for '
-                                     'the %s view deriver' % name)
-        else:
-            under = as_sorted_tuple(under)
+        if INGRESS in over:
+            raise ConfigurationError('%s cannot be over INGRESS' % name)
 
-        if over is not None and INGRESS in over:
-            raise ConfigurationError('%s cannot be over view deriver INGRESS'
-                                     % name)
+        # ensure everything is always over mapped_view
+        if VIEW in over and name != 'mapped_view':
+            over = as_sorted_tuple(over + ('mapped_view',))
 
-        if MAPPED_VIEW in under:
-            raise ConfigurationError('%s cannot be under view deriver '
-                                     'MAPPED_VIEW' % name)
+        if VIEW in under:
+            raise ConfigurationError('%s cannot be under VIEW' % name)
+        if 'mapped_view' in under:
+            raise ConfigurationError('%s cannot be under "mapped_view"' % name)
 
         discriminator = ('view deriver', name)
         intr = self.introspectable(
@@ -1173,7 +1173,7 @@ class ViewsConfiguratorMixin(object):
                     default_before=None,
                     default_after=INGRESS,
                     first=INGRESS,
-                    last=MAPPED_VIEW,
+                    last=VIEW,
                 )
                 self.registry.registerUtility(derivers, IViewDerivers)
             derivers.add(name, deriver, before=over, after=under)
@@ -1188,6 +1188,7 @@ class ViewsConfiguratorMixin(object):
             ('http_cached_view', d.http_cached_view),
             ('decorated_view', d.decorated_view),
             ('rendered_view', d.rendered_view),
+            ('mapped_view', d.mapped_view),
         ]
         last = INGRESS
         for name, deriver in derivers:
@@ -1195,12 +1196,10 @@ class ViewsConfiguratorMixin(object):
                 deriver,
                 name=name,
                 under=last,
-                over=MAPPED_VIEW,
+                over=VIEW,
             )
             last = name
 
-        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)
-
     def derive_view(self, view, attr=None, renderer=None):
         """
         Create a :term:`view callable` using the function, instance,
diff --git a/pyramid/viewderivers.py b/pyramid/viewderivers.py
index f97099cc8..8061e5d4a 100644
--- a/pyramid/viewderivers.py
+++ b/pyramid/viewderivers.py
@@ -455,5 +455,5 @@ def decorated_view(view, info):
 
 decorated_view.options = ('decorator',)
 
-MAPPED_VIEW = 'mapped_view'
+VIEW = 'VIEW'
 INGRESS = 'INGRESS'
 

{"pyramid/config/views.py": "import inspect\nimport posixpath\nimport operator\nimport os\nimport warnings\n\nfrom zope.interface import (\n    Interface,\n    implementedBy,\n    implementer,\n    )\n\nfrom zope.interface.interfaces import IInterface\n\nfrom pyramid.interfaces import (\n    IDefaultPermission,\n    IException,\n    IExceptionViewClassifier,\n    IMultiView,\n    IPackageOverrides,\n    IRendererFactory,\n    IRequest,\n    IResponse,\n    IRouteRequest,\n    ISecuredView,\n    IStaticURLInfo,\n    IView,\n    IViewClassifier,\n    IViewDerivers,\n    IViewDeriverInfo,\n    IViewMapperFactory,\n    PHASE1_CONFIG,\n    )\n\nfrom pyramid import renderers\n\nfrom pyramid.asset import resolve_asset_spec\nfrom pyramid.compat import (\n    string_types,\n    urlparse,\n    url_quote,\n    WIN,\n    is_nonstr_iter,\n    )\n\nfrom pyramid.decorator import reify\n\nfrom pyramid.exceptions import (\n    ConfigurationError,\n    PredicateMismatch,\n    )\n\nfrom pyramid.httpexceptions import (\n    HTTPForbidden,\n    HTTPNotFound,\n    default_exceptionresponse_view,\n    )\n\nfrom pyramid.registry import (\n    predvalseq,\n    Deferred,\n    )\n\nfrom pyramid.security import NO_PERMISSION_REQUIRED\nfrom pyramid.static import static_view\n\nfrom pyramid.url import parse_url_overrides\n\nfrom pyramid.view import AppendSlashNotFoundViewFactory\n\nimport pyramid.util\nfrom pyramid.util import (\n    viewdefaults,\n    action_method,\n    TopologicalSorter,\n    )\n\nimport pyramid.config.predicates\nimport pyramid.viewderivers\n\nfrom pyramid.viewderivers import (\n    INGRESS,\n    MAPPED_VIEW,\n    preserve_view_attrs,\n    view_description,\n    requestonly,\n    DefaultViewMapper,\n    wraps_view,\n)\n\nfrom pyramid.config.util import (\n    DEFAULT_PHASH,\n    MAX_ORDER,\n    as_sorted_tuple,\n    )\n\nurljoin = urlparse.urljoin\nurl_parse = urlparse.urlparse\n\nDefaultViewMapper = DefaultViewMapper # bw-compat\npreserve_view_attrs = preserve_view_attrs # bw-compat\nrequestonly = requestonly # bw-compat\nview_description = view_description # bw-compat\n\n@implementer(IMultiView)\nclass MultiView(object):\n\n    def __init__(self, name):\n        self.name = name\n        self.media_views = {}\n        self.views = []\n        self.accepts = []\n\n    def __discriminator__(self, context, request):\n        # used by introspection systems like so:\n        # view = adapters.lookup(....)\n        # view.__discriminator__(context, request) -> view's discriminator\n        # so that superdynamic systems can feed the discriminator to\n        # the introspection system to get info about it\n        view = self.match(context, request)\n        return view.__discriminator__(context, request)\n\n    def add(self, view, order, accept=None, phash=None):\n        if phash is not None:\n            for i, (s, v, h) in enumerate(list(self.views)):\n                if phash == h:\n                    self.views[i] = (order, view, phash)\n                    return\n\n        if accept is None or '*' in accept:\n            self.views.append((order, view, phash))\n            self.views.sort(key=operator.itemgetter(0))\n        else:\n            subset = self.media_views.setdefault(accept, [])\n            for i, (s, v, h) in enumerate(list(subset)):\n                if phash == h:\n                    subset[i] = (order, view, phash)\n                    return\n            else:\n                subset.append((order, view, phash))\n                subset.sort(key=operator.itemgetter(0))\n            accepts = set(self.accepts)\n            accepts.add(accept)\n            self.accepts = list(accepts) # dedupe\n\n    def get_views(self, request):\n        if self.accepts and hasattr(request, 'accept'):\n            accepts = self.accepts[:]\n            views = []\n            while accepts:\n                match = request.accept.best_match(accepts)\n                if match is None:\n                    break\n                subset = self.media_views[match]\n                views.extend(subset)\n                accepts.remove(match)\n            views.extend(self.views)\n            return views\n        return self.views\n\n    def match(self, context, request):\n        for order, view, phash in self.get_views(request):\n            if not hasattr(view, '__predicated__'):\n                return view\n            if view.__predicated__(context, request):\n                return view\n        raise PredicateMismatch(self.name)\n\n    def __permitted__(self, context, request):\n        view = self.match(context, request)\n        if hasattr(view, '__permitted__'):\n            return view.__permitted__(context, request)\n        return True\n\n    def __call_permissive__(self, context, request):\n        view = self.match(context, request)\n        view = getattr(view, '__call_permissive__', view)\n        return view(context, request)\n\n    def __call__(self, context, request):\n        for order, view, phash in self.get_views(request):\n            try:\n                return view(context, request)\n            except PredicateMismatch:\n                continue\n        raise PredicateMismatch(self.name)\n\nclass ViewsConfiguratorMixin(object):\n    @viewdefaults\n    @action_method\n    def add_view(\n        self,\n        view=None,\n        name=\"\",\n        for_=None,\n        permission=None,\n        request_type=None,\n        route_name=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        context=None,\n        decorator=None,\n        mapper=None,\n        http_cache=None,\n        match_param=None,\n        check_csrf=None,\n        **view_options):\n        \"\"\" Add a :term:`view configuration` to the current\n        configuration state.  Arguments to ``add_view`` are broken\n        down below into *predicate* arguments and *non-predicate*\n        arguments.  Predicate arguments narrow the circumstances in\n        which the view callable will be invoked when a request is\n        presented to :app:`Pyramid`; non-predicate arguments are\n        informational.\n\n        Non-Predicate Arguments\n\n        view\n\n          A :term:`view callable` or a :term:`dotted Python name`\n          which refers to a view callable.  This argument is required\n          unless a ``renderer`` argument also exists.  If a\n          ``renderer`` argument is passed, and a ``view`` argument is\n          not provided, the view callable defaults to a callable that\n          returns an empty dictionary (see\n          :ref:`views_which_use_a_renderer`).\n\n        permission\n\n          A :term:`permission` that the user must possess in order to invoke\n          the :term:`view callable`.  See :ref:`view_security_section` for\n          more information about view security and permissions.  This is\n          often a string like ``view`` or ``edit``.\n\n          If ``permission`` is omitted, a *default* permission may be used\n          for this view registration if one was named as the\n          :class:`pyramid.config.Configurator` constructor's\n          ``default_permission`` argument, or if\n          :meth:`pyramid.config.Configurator.set_default_permission` was used\n          prior to this view registration.  Pass the value\n          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission\n          argument to explicitly indicate that the view should always be\n          executable by entirely anonymous users, regardless of the default\n          permission, bypassing any :term:`authorization policy` that may be\n          in effect.\n\n        attr\n\n          This knob is most useful when the view definition is a class.\n\n          The view machinery defaults to using the ``__call__`` method\n          of the :term:`view callable` (or the function itself, if the\n          view callable is a function) to obtain a response.  The\n          ``attr`` value allows you to vary the method attribute used\n          to obtain the response.  For example, if your view was a\n          class, and the class has a method named ``index`` and you\n          wanted to use this method instead of the class' ``__call__``\n          method to return the response, you'd say ``attr=\"index\"`` in the\n          view configuration for the view.\n\n        renderer\n\n          This is either a single string term (e.g. ``json``) or a\n          string implying a path or :term:`asset specification`\n          (e.g. ``templates/views.pt``) naming a :term:`renderer`\n          implementation.  If the ``renderer`` value does not contain\n          a dot ``.``, the specified string will be used to look up a\n          renderer implementation, and that renderer implementation\n          will be used to construct a response from the view return\n          value.  If the ``renderer`` value contains a dot (``.``),\n          the specified term will be treated as a path, and the\n          filename extension of the last element in the path will be\n          used to look up the renderer implementation, which will be\n          passed the full path.  The renderer implementation will be\n          used to construct a :term:`response` from the view return\n          value.\n\n          Note that if the view itself returns a :term:`response` (see\n          :ref:`the_response`), the specified renderer implementation\n          is never called.\n\n          When the renderer is a path, although a path is usually just\n          a simple relative pathname (e.g. ``templates/foo.pt``,\n          implying that a template named \"foo.pt\" is in the\n          \"templates\" directory relative to the directory of the\n          current :term:`package` of the Configurator), a path can be\n          absolute, starting with a slash on UNIX or a drive letter\n          prefix on Windows.  The path can alternately be a\n          :term:`asset specification` in the form\n          ``some.dotted.package_name:relative/path``, making it\n          possible to address template assets which live in a\n          separate package.\n\n          The ``renderer`` attribute is optional.  If it is not\n          defined, the \"null\" renderer is assumed (no rendering is\n          performed and the value is passed back to the upstream\n          :app:`Pyramid` machinery unmodified).\n\n        http_cache\n\n          .. versionadded:: 1.1\n\n          When you supply an ``http_cache`` value to a view configuration,\n          the ``Expires`` and ``Cache-Control`` headers of a response\n          generated by the associated view callable are modified.  The value\n          for ``http_cache`` may be one of the following:\n\n          - A nonzero integer.  If it's a nonzero integer, it's treated as a\n            number of seconds.  This number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=3600`` instructs the requesting browser\n            to 'cache this response for an hour, please'.\n\n          - A ``datetime.timedelta`` instance.  If it's a\n            ``datetime.timedelta`` instance, it will be converted into a\n            number of seconds, and that number of seconds will be used to\n            compute the ``Expires`` header and the ``Cache-Control:\n            max-age`` parameter of responses to requests which call this view.\n            For example: ``http_cache=datetime.timedelta(days=1)`` instructs\n            the requesting browser to 'cache this response for a day, please'.\n\n          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and\n            ``Expires`` headers present in all responses from this view will\n            be composed such that client browser cache (and any intermediate\n            caches) are instructed to never cache the response.\n\n          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,\n            {'public':True})``), the first value in the tuple may be a\n            nonzero integer or a ``datetime.timedelta`` instance; in either\n            case this value will be used as the number of seconds to cache\n            the response.  The second value in the tuple must be a\n            dictionary.  The values present in the dictionary will be used as\n            input to the ``Cache-Control`` response header.  For example:\n            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,\n            and add ``public`` to the Cache-Control header of the response'.\n            All keys and values supported by the\n            ``webob.cachecontrol.CacheControl`` interface may be added to the\n            dictionary.  Supplying ``{'public':True}`` is equivalent to\n            calling ``response.cache_control.public = True``.\n\n          Providing a non-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value)`` within your view's body.\n\n          Providing a two-tuple value as ``http_cache`` is equivalent to\n          calling ``response.cache_expires(value[0], **value[1])`` within your\n          view's body.\n\n          If you wish to avoid influencing, the ``Expires`` header, and\n          instead wish to only influence ``Cache-Control`` headers, pass a\n          tuple as ``http_cache`` with the first element of ``None``, e.g.:\n          ``(None, {'public':True})``.\n\n          If you wish to prevent a view that uses ``http_cache`` in its\n          configuration from having its caching response headers changed by\n          this machinery, set ``response.cache_control.prevent_auto = True``\n          before returning the response from the view.  This effectively\n          disables any HTTP caching done by ``http_cache`` for that response.\n\n        wrapper\n\n          The :term:`view name` of a different :term:`view\n          configuration` which will receive the response body of this\n          view as the ``request.wrapped_body`` attribute of its own\n          :term:`request`, and the :term:`response` returned by this\n          view as the ``request.wrapped_response`` attribute of its\n          own request.  Using a wrapper makes it possible to \"chain\"\n          views together to form a composite response.  The response\n          of the outermost wrapper view will be returned to the user.\n          The wrapper view will be found as any view is found: see\n          :ref:`view_lookup`.  The \"best\" wrapper view will be found\n          based on the lookup ordering: \"under the hood\" this wrapper\n          view is looked up via\n          ``pyramid.view.render_view_to_response(context, request,\n          'wrapper_viewname')``. The context and request of a wrapper\n          view is the same context and request of the inner view.  If\n          this attribute is unspecified, no view wrapping is done.\n\n        decorator\n\n          A :term:`dotted Python name` to function (or the function itself,\n          or an iterable of the aforementioned) which will be used to\n          decorate the registered :term:`view callable`.  The decorator\n          function(s) will be called with the view callable as a single\n          argument.  The view callable it is passed will accept\n          ``(context, request)``.  The decorator(s) must return a\n          replacement view callable which also accepts ``(context,\n          request)``.\n\n          If decorator is an iterable, the callables will be combined and\n          used in the order provided as a decorator.\n          For example::\n\n            @view_config(...,\n                decorator=(decorator2,\n                           decorator1))\n            def myview(request):\n                ....\n\n          Is similar to doing::\n\n            @view_config(...)\n            @decorator2\n            @decorator1\n            def myview(request):\n                ...\n\n          Except with the existing benefits of ``decorator=`` (having a common\n          decorator syntax for all view calling conventions and not having to\n          think about preserving function attributes such as ``__name__`` and\n          ``__module__`` within decorator logic).\n\n          All view callables in the decorator chain must return a response\n          object implementing :class:`pyramid.interfaces.IResponse` or raise\n          an exception:\n\n          .. code-block:: python\n\n             def log_timer(wrapped):\n                 def wrapper(context, request):\n                     start = time.time()\n                     response = wrapped(context, request)\n                     duration = time.time() - start\n                     response.headers['X-View-Time'] = '%.3f' % (duration,)\n                     log.info('view took %.3f seconds', duration)\n                     return response\n                 return wrapper\n\n          .. versionchanged:: 1.4a4\n             Passing an iterable.\n\n        mapper\n\n          A Python object or :term:`dotted Python name` which refers to a\n          :term:`view mapper`, or ``None``.  By default it is ``None``, which\n          indicates that the view should use the default view mapper.  This\n          plug-point is useful for Pyramid extension developers, but it's not\n          very useful for 'civilians' who are just developing stock Pyramid\n          applications. Pay no attention to the man behind the curtain.\n\n        accept\n\n          This value represents a match query for one or more mimetypes in the\n          ``Accept`` HTTP request header.  If this value is specified, it must\n          be in one of the following forms: a mimetype match token in the form\n          ``text/plain``, a wildcard mimetype match token in the form\n          ``text/*`` or a match-all wildcard mimetype match token in the form\n          ``*/*``.  If any of the forms matches the ``Accept`` header of the\n          request, or if the ``Accept`` header isn't set at all in the request,\n          this will match the current view. If this does not match the\n          ``Accept`` header of the request, view matching continues.\n\n        Predicate Arguments\n\n        name\n\n          The :term:`view name`.  Read :ref:`traversal_chapter` to\n          understand the concept of a view name.\n\n        context\n\n          An object or a :term:`dotted Python name` referring to an\n          interface or class object that the :term:`context` must be\n          an instance of, *or* the :term:`interface` that the\n          :term:`context` must provide in order for this view to be\n          found and called.  This predicate is true when the\n          :term:`context` is an instance of the represented class or\n          if the :term:`context` provides the represented interface;\n          it is otherwise false.  This argument may also be provided\n          to ``add_view`` as ``for_`` (an older, still-supported\n          spelling).\n\n        route_name\n\n          This value must match the ``name`` of a :term:`route\n          configuration` declaration (see :ref:`urldispatch_chapter`)\n          that must match before this view will be called.\n\n        request_type\n\n          This value should be an :term:`interface` that the\n          :term:`request` must provide in order for this view to be\n          found and called.  This value exists only for backwards\n          compatibility purposes.\n\n        request_method\n\n          This value can be either a string (such as ``\"GET\"``, ``\"POST\"``,\n          ``\"PUT\"``, ``\"DELETE\"``, ``\"HEAD\"`` or ``\"OPTIONS\"``) representing\n          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of\n          these strings.  A view declaration with this argument ensures that\n          the view will only be called when the ``method`` attribute of the\n          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches\n          a supplied value.  Note that use of ``GET`` also implies that the\n          view will respond to ``HEAD`` as of Pyramid 1.4.\n\n          .. versionchanged:: 1.2\n             The ability to pass a tuple of items as ``request_method``.\n             Previous versions allowed only a string.\n\n        request_param\n\n          This value can be any string or any sequence of strings.  A view\n          declaration with this argument ensures that the view will only be\n          called when the :term:`request` has a key in the ``request.params``\n          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a\n          name which matches the supplied value (if the value is a string)\n          or values (if the value is a tuple).  If any value\n          supplied has a ``=`` sign in it,\n          e.g. ``request_param=\"foo=123\"``, then the key (``foo``)\n          must both exist in the ``request.params`` dictionary, *and*\n          the value must match the right hand side of the expression\n          (``123``) for the view to \"match\" the current request.\n\n        match_param\n\n          .. versionadded:: 1.2\n\n          This value can be a string of the format \"key=value\" or a tuple\n          containing one or more of these strings.\n\n          A view declaration with this argument ensures that the view will\n          only be called when the :term:`request` has key/value pairs in its\n          :term:`matchdict` that equal those supplied in the predicate.\n          e.g. ``match_param=\"action=edit\"`` would require the ``action``\n          parameter in the :term:`matchdict` match the right hand side of\n          the expression (``edit``) for the view to \"match\" the current\n          request.\n\n          If the ``match_param`` is a tuple, every key/value pair must match\n          for the predicate to pass.\n\n        containment\n\n          This value should be a Python class or :term:`interface` (or a\n          :term:`dotted Python name`) that an object in the\n          :term:`lineage` of the context must provide in order for this view\n          to be found and called.  The nodes in your object graph must be\n          \"location-aware\" to use this feature.  See\n          :ref:`location_aware` for more information about\n          location-awareness.\n\n        xhr\n\n          This value should be either ``True`` or ``False``.  If this\n          value is specified and is ``True``, the :term:`request`\n          must possess an ``HTTP_X_REQUESTED_WITH`` (aka\n          ``X-Requested-With``) header that has the value\n          ``XMLHttpRequest`` for this view to be found and called.\n          This is useful for detecting AJAX requests issued from\n          jQuery, Prototype and other Javascript libraries.\n\n        header\n\n          This value represents an HTTP header name or a header\n          name/value pair.  If the value contains a ``:`` (colon), it\n          will be considered a name/value pair\n          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The\n          value portion should be a regular expression.  If the value\n          does not contain a colon, the entire value will be\n          considered to be the header name\n          (e.g. ``If-Modified-Since``).  If the value evaluates to a\n          header name only without a value, the header specified by\n          the name must be present in the request for this predicate\n          to be true.  If the value evaluates to a header name/value\n          pair, the header specified by the name must be present in\n          the request *and* the regular expression specified as the\n          value must match the header value.  Whether or not the value\n          represents a header name or a header name/value pair, the\n          case of the header name is not significant.\n\n        path_info\n\n          This value represents a regular expression pattern that will\n          be tested against the ``PATH_INFO`` WSGI environment\n          variable.  If the regex matches, this predicate will be\n          ``True``.\n\n        check_csrf\n\n          If specified, this value should be one of ``None``, ``True``,\n          ``False``, or a string representing the 'check name'.  If the value\n          is ``True`` or a string, CSRF checking will be performed.  If the\n          value is ``False`` or ``None``, CSRF checking will not be performed.\n\n          If the value provided is a string, that string will be used as the\n          'check name'.  If the value provided is ``True``, ``csrf_token`` will\n          be used as the check name.\n\n          If CSRF checking is performed, the checked value will be the value\n          of ``request.params[check_name]``.  This value will be compared\n          against the value of ``request.session.get_csrf_token()``, and the\n          check will pass if these two values are the same.  If the check\n          passes, the associated view will be permitted to execute.  If the\n          check fails, the associated view will not be permitted to execute.\n\n          Note that using this feature requires a :term:`session factory` to\n          have been configured.\n\n          .. versionadded:: 1.4a2\n\n        physical_path\n\n          If specified, this value should be a string or a tuple representing\n          the :term:`physical path` of the context found via traversal for this\n          predicate to match as true.  For example: ``physical_path='/'`` or\n          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.\n          This is not a path prefix match or a regex, it's a whole-path match.\n          It's useful when you want to always potentially show a view when some\n          object is traversed to, but you can't be sure about what kind of\n          object it will be, so you can't use the ``context`` predicate.  The\n          individual path elements inbetween slash characters or in tuple\n          elements should be the Unicode representation of the name of the\n          resource and should not be encoded in any way.\n\n          .. versionadded:: 1.4a3\n\n        effective_principals\n\n          If specified, this value should be a :term:`principal` identifier or\n          a sequence of principal identifiers.  If the\n          :attr:`pyramid.request.Request.effective_principals` property\n          indicates that every principal named in the argument list is present\n          in the current request, this predicate will return True; otherwise it\n          will return False.  For example:\n          ``effective_principals=pyramid.security.Authenticated`` or\n          ``effective_principals=('fred', 'group:admins')``.\n\n          .. versionadded:: 1.4a4\n\n        custom_predicates\n\n            .. deprecated:: 1.5\n                This value should be a sequence of references to custom\n                predicate callables.  Use custom predicates when no set of\n                predefined predicates do what you need.  Custom predicates\n                can be combined with predefined predicates as necessary.\n                Each custom predicate callable should accept two arguments:\n                ``context`` and ``request`` and should return either\n                ``True`` or ``False`` after doing arbitrary evaluation of\n                the context and/or the request.  The ``predicates`` argument\n                to this method and the ability to register third-party view\n                predicates via\n                :meth:`pyramid.config.Configurator.add_view_predicate`\n                obsoletes this argument, but it is kept around for backwards\n                compatibility.\n\n        view_options:\n\n          Pass a key/value pair here to use a third-party predicate or set a\n          value for a view deriver. See\n          :meth:`pyramid.config.Configurator.add_view_predicate` and\n          :meth:`pyramid.config.Configurator.add_view_deriver`. See\n          :ref:`view_and_route_predicates` for more information about\n          third-party predicates and :ref:`view_derivers` for information\n          about view derivers.\n\n          .. versionadded: 1.4a1\n\n          .. versionchanged: 1.7\n\n             Support setting view deriver options. Previously, only custom\n             view predicate values could be supplied.\n\n        \"\"\"\n        if custom_predicates:\n            warnings.warn(\n                ('The \"custom_predicates\" argument to Configurator.add_view '\n                 'is deprecated as of Pyramid 1.5.  Use '\n                 '\"config.add_view_predicate\" and use the registered '\n                 'view predicate as a predicate argument to add_view instead. '\n                 'See \"Adding A Third Party View, Route, or Subscriber '\n                 'Predicate\" in the \"Hooks\" chapter of the documentation '\n                 'for more information.'),\n                DeprecationWarning,\n                stacklevel=4\n                )\n\n        view = self.maybe_dotted(view)\n        context = self.maybe_dotted(context)\n        for_ = self.maybe_dotted(for_)\n        containment = self.maybe_dotted(containment)\n        mapper = self.maybe_dotted(mapper)\n\n        def combine(*decorators):\n            def decorated(view_callable):\n                # reversed() allows a more natural ordering in the api\n                for decorator in reversed(decorators):\n                    view_callable = decorator(view_callable)\n                return view_callable\n            return decorated\n\n        if is_nonstr_iter(decorator):\n            decorator = combine(*map(self.maybe_dotted, decorator))\n        else:\n            decorator = self.maybe_dotted(decorator)\n\n        if not view:\n            if renderer:\n                def view(context, request):\n                    return {}\n            else:\n                raise ConfigurationError('\"view\" was not specified and '\n                                         'no \"renderer\" specified')\n\n        if request_type is not None:\n            request_type = self.maybe_dotted(request_type)\n            if not IInterface.providedBy(request_type):\n                raise ConfigurationError(\n                    'request_type must be an interface, not %s' % request_type)\n\n        if context is None:\n            context = for_\n\n        r_context = context\n        if r_context is None:\n            r_context = Interface\n        if not IInterface.providedBy(r_context):\n            r_context = implementedBy(r_context)\n\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n\n        if accept is not None:\n            accept = accept.lower()\n\n        introspectables = []\n        ovals = view_options.copy()\n        ovals.update(dict(\n            xhr=xhr,\n            request_method=request_method,\n            path_info=path_info,\n            request_param=request_param,\n            header=header,\n            accept=accept,\n            containment=containment,\n            request_type=request_type,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            custom=predvalseq(custom_predicates),\n        ))\n\n        def discrim_func():\n            # We need to defer the discriminator until we know what the phash\n            # is.  It can't be computed any sooner because thirdparty\n            # predicates/view derivers may not yet exist when add_view is\n            # called.\n            valid_predicates = predlist.names()\n            pvals = {}\n            dvals = {}\n\n            for (k, v) in ovals.items():\n                if k in valid_predicates:\n                    pvals[k] = v\n                else:\n                    dvals[k] = v\n\n            self._check_view_options(**dvals)\n\n            order, preds, phash = predlist.make(self, **pvals)\n\n            view_intr.update({\n                'phash': phash,\n                'order': order,\n                'predicates': preds,\n                })\n            return ('view', context, name, route_name, phash)\n\n        discriminator = Deferred(discrim_func)\n\n        if inspect.isclass(view) and attr:\n            view_desc = 'method %r of %s' % (\n                attr, self.object_description(view))\n        else:\n            view_desc = self.object_description(view)\n\n        tmpl_intr = None\n\n        view_intr = self.introspectable('views',\n                                        discriminator,\n                                        view_desc,\n                                        'view')\n        view_intr.update(dict(\n            name=name,\n            context=context,\n            containment=containment,\n            request_param=request_param,\n            request_methods=request_method,\n            route_name=route_name,\n            attr=attr,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            match_param=match_param,\n            check_csrf=check_csrf,\n            callable=view,\n            mapper=mapper,\n            decorator=decorator,\n        ))\n        view_intr.update(view_options)\n        introspectables.append(view_intr)\n        predlist = self.get_predlist('view')\n\n        def register(permission=permission, renderer=renderer):\n            request_iface = IRequest\n            if route_name is not None:\n                request_iface = self.registry.queryUtility(IRouteRequest,\n                                                           name=route_name)\n                if request_iface is None:\n                    # route configuration should have already happened in\n                    # phase 2\n                    raise ConfigurationError(\n                        'No route named %s found for view registration' %\n                        route_name)\n\n            if renderer is None:\n                # use default renderer if one exists (reg'd in phase 1)\n                if self.registry.queryUtility(IRendererFactory) is not None:\n                    renderer = renderers.RendererHelper(\n                        name=None,\n                        package=self.package,\n                        registry=self.registry\n                        )\n\n            if permission is None:\n                # intent: will be None if no default permission is registered\n                # (reg'd in phase 1)\n                permission = self.registry.queryUtility(IDefaultPermission)\n\n            # added by discrim_func above during conflict resolving\n            preds = view_intr['predicates']\n            order = view_intr['order']\n            phash = view_intr['phash']\n\n            # __no_permission_required__ handled by _secure_view\n            derived_view = self._derive_view(\n                view,\n                permission=permission,\n                predicates=preds,\n                attr=attr,\n                context=context,\n                renderer=renderer,\n                wrapper_viewname=wrapper,\n                viewname=name,\n                accept=accept,\n                order=order,\n                phash=phash,\n                decorator=decorator,\n                mapper=mapper,\n                http_cache=http_cache,\n                extra_options=ovals,\n            )\n            derived_view.__discriminator__ = lambda *arg: discriminator\n            # __discriminator__ is used by superdynamic systems\n            # that require it for introspection after manual view lookup;\n            # see also MultiView.__discriminator__\n            view_intr['derived_callable'] = derived_view\n\n            registered = self.registry.adapters.registered\n\n            # A multiviews is a set of views which are registered for\n            # exactly the same context type/request type/name triad.  Each\n            # consituent view in a multiview differs only by the\n            # predicates which it possesses.\n\n            # To find a previously registered view for a context\n            # type/request type/name triad, we need to use the\n            # ``registered`` method of the adapter registry rather than\n            # ``lookup``.  ``registered`` ignores interface inheritance\n            # for the required and provided arguments, returning only a\n            # view registered previously with the *exact* triad we pass\n            # in.\n\n            # We need to do this three times, because we use three\n            # different interfaces as the ``provided`` interface while\n            # doing registrations, and ``registered`` performs exact\n            # matches on all the arguments it receives.\n\n            old_view = None\n\n            for view_type in (IView, ISecuredView, IMultiView):\n                old_view = registered((IViewClassifier, request_iface,\n                                       r_context), view_type, name)\n                if old_view is not None:\n                    break\n\n            isexc = isexception(context)\n\n            def regclosure():\n                if hasattr(derived_view, '__call_permissive__'):\n                    view_iface = ISecuredView\n                else:\n                    view_iface = IView\n                self.registry.registerAdapter(\n                    derived_view,\n                    (IViewClassifier, request_iface, context), view_iface, name\n                    )\n                if isexc:\n                    self.registry.registerAdapter(\n                        derived_view,\n                        (IExceptionViewClassifier, request_iface, context),\n                        view_iface, name)\n\n            is_multiview = IMultiView.providedBy(old_view)\n            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)\n\n            if old_view is None:\n                # - No component was yet registered for any of our I*View\n                #   interfaces exactly; this is the first view for this\n                #   triad.\n                regclosure()\n\n            elif (not is_multiview) and (old_phash == phash):\n                # - A single view component was previously registered with\n                #   the same predicate hash as this view; this registration\n                #   is therefore an override.\n                regclosure()\n\n            else:\n                # - A view or multiview was already registered for this\n                #   triad, and the new view is not an override.\n\n                # XXX we could try to be more efficient here and register\n                # a non-secured view for a multiview if none of the\n                # multiview's consituent views have a permission\n                # associated with them, but this code is getting pretty\n                # rough already\n                if is_multiview:\n                    multiview = old_view\n                else:\n                    multiview = MultiView(name)\n                    old_accept = getattr(old_view, '__accept__', None)\n                    old_order = getattr(old_view, '__order__', MAX_ORDER)\n                    multiview.add(old_view, old_order, old_accept, old_phash)\n                multiview.add(derived_view, order, accept, phash)\n                for view_type in (IView, ISecuredView):\n                    # unregister any existing views\n                    self.registry.adapters.unregister(\n                        (IViewClassifier, request_iface, r_context),\n                        view_type, name=name)\n                    if isexc:\n                        self.registry.adapters.unregister(\n                            (IExceptionViewClassifier, request_iface,\n                             r_context), view_type, name=name)\n                self.registry.registerAdapter(\n                    multiview,\n                    (IViewClassifier, request_iface, context),\n                    IMultiView, name=name)\n                if isexc:\n                    self.registry.registerAdapter(\n                        multiview,\n                        (IExceptionViewClassifier, request_iface, context),\n                        IMultiView, name=name)\n\n            self.registry._clear_view_lookup_cache()\n            renderer_type = getattr(renderer, 'type', None) # gard against None\n            intrspc = self.introspector\n            if (\n                renderer_type is not None and\n                tmpl_intr is not None and\n                intrspc is not None and\n                intrspc.get('renderer factories', renderer_type) is not None\n                ):\n                # allow failure of registered template factories to be deferred\n                # until view execution, like other bad renderer factories; if\n                # we tried to relate this to an existing renderer factory\n                # without checking if it the factory actually existed, we'd end\n                # up with a KeyError at startup time, which is inconsistent\n                # with how other bad renderer registrations behave (they throw\n                # a ValueError at view execution time)\n                tmpl_intr.relate('renderer factories', renderer.type)\n\n        if mapper:\n            mapper_intr = self.introspectable(\n                'view mappers',\n                discriminator,\n                'view mapper for %s' % view_desc,\n                'view mapper'\n                )\n            mapper_intr['mapper'] = mapper\n            mapper_intr.relate('views', discriminator)\n            introspectables.append(mapper_intr)\n        if route_name:\n            view_intr.relate('routes', route_name) # see add_route\n        if renderer is not None and renderer.name and '.' in renderer.name:\n            # the renderer is a template\n            tmpl_intr = self.introspectable(\n                'templates',\n                discriminator,\n                renderer.name,\n                'template'\n                )\n            tmpl_intr.relate('views', discriminator)\n            tmpl_intr['name'] = renderer.name\n            tmpl_intr['type'] = renderer.type\n            tmpl_intr['renderer'] = renderer\n            introspectables.append(tmpl_intr)\n        if permission is not None:\n            # if a permission exists, register a permission introspectable\n            perm_intr = self.introspectable(\n                'permissions',\n                permission,\n                permission,\n                'permission'\n                )\n            perm_intr['value'] = permission\n            perm_intr.relate('views', discriminator)\n            introspectables.append(perm_intr)\n        self.action(discriminator, register, introspectables=introspectables)\n\n    def _check_view_options(self, **kw):\n        # we only need to validate deriver options because the predicates\n        # were checked by the predlist\n        derivers = self.registry.getUtility(IViewDerivers)\n        for deriver in derivers.values():\n            for opt in getattr(deriver, 'options', []):\n                kw.pop(opt, None)\n        if kw:\n            raise ConfigurationError('Unknown view options: %s' % (kw,))\n\n    def _apply_view_derivers(self, info):\n        d = pyramid.viewderivers\n\n        # These derivers are not really derivers and so have fixed order\n        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),\n                          ('predicated_view', d.predicated_view)]\n\n        view = info.original_view\n        derivers = self.registry.getUtility(IViewDerivers)\n        for name, deriver in reversed(outer_derivers + derivers.sorted()):\n            view = wraps_view(deriver)(view, info)\n        return view\n\n    @action_method\n    def add_view_predicate(self, name, factory, weighs_more_than=None,\n                           weighs_less_than=None):\n        \"\"\"\n        .. versionadded:: 1.4\n\n        Adds a view predicate factory.  The associated view predicate can\n        later be named as a keyword argument to\n        :meth:`pyramid.config.Configurator.add_view` in the\n        ``predicates`` anonyous keyword argument dictionary.\n\n        ``name`` should be the name of the predicate.  It must be a valid\n        Python identifier (it will be used as a keyword argument to\n        ``add_view`` by others).\n\n        ``factory`` should be a :term:`predicate factory` or :term:`dotted\n        Python name` which refers to a predicate factory.\n\n        See :ref:`view_and_route_predicates` for more information.\n        \"\"\"\n        self._add_predicate(\n            'view',\n            name,\n            factory,\n            weighs_more_than=weighs_more_than,\n            weighs_less_than=weighs_less_than\n            )\n\n    def add_default_view_predicates(self):\n        p = pyramid.config.predicates\n        for (name, factory) in (\n            ('xhr', p.XHRPredicate),\n            ('request_method', p.RequestMethodPredicate),\n            ('path_info', p.PathInfoPredicate),\n            ('request_param', p.RequestParamPredicate),\n            ('header', p.HeaderPredicate),\n            ('accept', p.AcceptPredicate),\n            ('containment', p.ContainmentPredicate),\n            ('request_type', p.RequestTypePredicate),\n            ('match_param', p.MatchParamPredicate),\n            ('check_csrf', p.CheckCSRFTokenPredicate),\n            ('physical_path', p.PhysicalPathPredicate),\n            ('effective_principals', p.EffectivePrincipalsPredicate),\n            ('custom', p.CustomPredicate),\n            ):\n            self.add_view_predicate(name, factory)\n\n    @action_method\n    def add_view_deriver(self, deriver, name=None, under=None, over=None):\n        \"\"\"\n        .. versionadded:: 1.7\n\n        Add a :term:`view deriver` to the view pipeline. View derivers are\n        a feature used by extension authors to wrap views in custom code\n        controllable by view-specific options.\n\n        ``deriver`` should be a callable conforming to the\n        :class:`pyramid.interfaces.IViewDeriver` interface.\n\n        ``name`` should be the name of the view deriver.  There are no\n        restrictions on the name of a view deriver. If left unspecified, the\n        name will be constructed from the name of the ``deriver``.\n\n        The ``under`` and ``over`` options can be used to control the ordering\n        of view derivers by providing hints about where in the view pipeline\n        the deriver is used. Each option may be a string or a list of strings.\n        At least one view deriver in each, the over and under directions, must\n        exist to fully satisfy the constraints.\n\n        ``under`` means closer to the user-defined :term:`view callable`,\n        and ``over`` means closer to view pipeline ingress.\n\n        Specifying neither ``under`` nor ``over`` is equivalent to specifying\n        ``over='rendered_view'`` and ``under='decorated_view'``, placing the\n        deriver somewhere between the ``decorated_view`` and ``rendered_view``\n        derivers.\n\n        See :ref:`view_derivers` for more information.\n\n        \"\"\"\n        deriver = self.maybe_dotted(deriver)\n\n        if name is None:\n            name = deriver.__name__\n\n        if name in (INGRESS,):\n            raise ConfigurationError('%s is a reserved view deriver name'\n                                     % name)\n\n        if under is None and over is None:\n            under = 'decorated_view'\n            over = 'rendered_view'\n\n        if over is None and name != MAPPED_VIEW:\n            raise ConfigurationError('must specify an \"over\" constraint for '\n                                     'the %s view deriver' % name)\n        elif over is not None:\n            over = as_sorted_tuple(over)\n\n        if under is None:\n            raise ConfigurationError('must specify an \"under\" constraint for '\n                                     'the %s view deriver' % name)\n        else:\n            under = as_sorted_tuple(under)\n\n        if over is not None and INGRESS in over:\n            raise ConfigurationError('%s cannot be over view deriver INGRESS'\n                                     % name)\n\n        if MAPPED_VIEW in under:\n            raise ConfigurationError('%s cannot be under view deriver '\n                                     'MAPPED_VIEW' % name)\n\n        discriminator = ('view deriver', name)\n        intr = self.introspectable(\n            'view derivers',\n            name,\n            name,\n            'view deriver')\n        intr['name'] = name\n        intr['deriver'] = deriver\n        intr['under'] = under\n        intr['over'] = over\n        def register():\n            derivers = self.registry.queryUtility(IViewDerivers)\n            if derivers is None:\n                derivers = TopologicalSorter(\n                    default_before=None,\n                    default_after=INGRESS,\n                    first=INGRESS,\n                    last=MAPPED_VIEW,\n                )\n                self.registry.registerUtility(derivers, IViewDerivers)\n            derivers.add(name, deriver, before=over, after=under)\n        self.action(discriminator, register, introspectables=(intr,),\n                    order=PHASE1_CONFIG) # must be registered before add_view\n\n    def add_default_view_derivers(self):\n        d = pyramid.viewderivers\n        derivers = [\n            ('secured_view', d.secured_view),\n            ('owrapped_view', d.owrapped_view),\n            ('http_cached_view', d.http_cached_view),\n            ('decorated_view', d.decorated_view),\n            ('rendered_view', d.rendered_view),\n        ]\n        last = INGRESS\n        for name, deriver in derivers:\n            self.add_view_deriver(\n                deriver,\n                name=name,\n                under=last,\n                over=MAPPED_VIEW,\n            )\n            last = name\n\n        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)\n\n    def derive_view(self, view, attr=None, renderer=None):\n        \"\"\"\n        Create a :term:`view callable` using the function, instance,\n        or class (or :term:`dotted Python name` referring to the same)\n        provided as ``view`` object.\n\n        .. warning::\n\n           This method is typically only used by :app:`Pyramid` framework\n           extension authors, not by :app:`Pyramid` application developers.\n\n        This is API is useful to framework extenders who create\n        pluggable systems which need to register 'proxy' view\n        callables for functions, instances, or classes which meet the\n        requirements of being a :app:`Pyramid` view callable.  For\n        example, a ``some_other_framework`` function in another\n        framework may want to allow a user to supply a view callable,\n        but he may want to wrap the view callable in his own before\n        registering the wrapper as a :app:`Pyramid` view callable.\n        Because a :app:`Pyramid` view callable can be any of a\n        number of valid objects, the framework extender will not know\n        how to call the user-supplied object.  Running it through\n        ``derive_view`` normalizes it to a callable which accepts two\n        arguments: ``context`` and ``request``.\n\n        For example:\n\n        .. code-block:: python\n\n           def some_other_framework(user_supplied_view):\n               config = Configurator(reg)\n               proxy_view = config.derive_view(user_supplied_view)\n               def my_wrapper(context, request):\n                   do_something_that_mutates(request)\n                   return proxy_view(context, request)\n               config.add_view(my_wrapper)\n\n        The ``view`` object provided should be one of the following:\n\n        - A function or another non-class callable object that accepts\n          a :term:`request` as a single positional argument and which\n          returns a :term:`response` object.\n\n        - A function or other non-class callable object that accepts\n          two positional arguments, ``context, request`` and which\n          returns a :term:`response` object.\n\n        - A class which accepts a single positional argument in its\n          constructor named ``request``, and which has a ``__call__``\n          method that accepts no arguments that returns a\n          :term:`response` object.\n\n        - A class which accepts two positional arguments named\n          ``context, request``, and which has a ``__call__`` method\n          that accepts no arguments that returns a :term:`response`\n          object.\n\n        - A :term:`dotted Python name` which refers to any of the\n          kinds of objects above.\n\n        This API returns a callable which accepts the arguments\n        ``context, request`` and which returns the result of calling\n        the provided ``view`` object.\n\n        The ``attr`` keyword argument is most useful when the view\n        object is a class.  It names the method that should be used as\n        the callable.  If ``attr`` is not provided, the attribute\n        effectively defaults to ``__call__``.  See\n        :ref:`class_as_view` for more information.\n\n        The ``renderer`` keyword argument should be a renderer\n        name. If supplied, it will cause the returned callable to use\n        a :term:`renderer` to convert the user-supplied view result to\n        a :term:`response` object.  If a ``renderer`` argument is not\n        supplied, the user-supplied view must itself return a\n        :term:`response` object.  \"\"\"\n        return self._derive_view(view, attr=attr, renderer=renderer)\n\n    # b/w compat\n    def _derive_view(self, view, permission=None, predicates=(),\n                     attr=None, renderer=None, wrapper_viewname=None,\n                     viewname=None, accept=None, order=MAX_ORDER,\n                     phash=DEFAULT_PHASH, decorator=None,\n                     mapper=None, http_cache=None, context=None,\n                     extra_options=None):\n        view = self.maybe_dotted(view)\n        mapper = self.maybe_dotted(mapper)\n        if isinstance(renderer, string_types):\n            renderer = renderers.RendererHelper(\n                name=renderer, package=self.package,\n                registry=self.registry)\n        if renderer is None:\n            # use default renderer if one exists\n            if self.registry.queryUtility(IRendererFactory) is not None:\n                renderer = renderers.RendererHelper(\n                    name=None,\n                    package=self.package,\n                    registry=self.registry)\n\n        options = dict(\n            view=view,\n            context=context,\n            permission=permission,\n            attr=attr,\n            renderer=renderer,\n            wrapper=wrapper_viewname,\n            name=viewname,\n            accept=accept,\n            mapper=mapper,\n            decorator=decorator,\n            http_cache=http_cache,\n        )\n        if extra_options:\n            options.update(extra_options)\n\n        info = ViewDeriverInfo(\n            view=view,\n            registry=self.registry,\n            package=self.package,\n            predicates=predicates,\n            options=options,\n        )\n\n        # order and phash are only necessary for the predicated view and\n        # are not really view deriver options\n        info.order = order\n        info.phash = phash\n\n        return self._apply_view_derivers(info)\n\n    @viewdefaults\n    @action_method\n    def add_forbidden_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        **view_options\n        ):\n        \"\"\" Add a forbidden view to the current configuration state.  The\n        view will be called when Pyramid or application code raises a\n        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of\n        circumstances implied by the predicates provided are matched.  The\n        simplest example is:\n\n          .. code-block:: python\n\n            def forbidden(request):\n                return Response('Forbidden', status='403 Forbidden')\n\n            config.add_forbidden_view(forbidden)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this forbidden\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a forbidden view.\n\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_forbidden_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPForbidden,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            attr=attr,\n            renderer=renderer,\n            )\n        settings.update(view_options)\n        return self.add_view(**settings)\n\n    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias\n\n    @viewdefaults\n    @action_method\n    def add_notfound_view(\n        self,\n        view=None,\n        attr=None,\n        renderer=None,\n        wrapper=None,\n        route_name=None,\n        request_type=None,\n        request_method=None,\n        request_param=None,\n        containment=None,\n        xhr=None,\n        accept=None,\n        header=None,\n        path_info=None,\n        custom_predicates=(),\n        decorator=None,\n        mapper=None,\n        match_param=None,\n        append_slash=False,\n        **view_options\n        ):\n        \"\"\" Add a default Not Found View to the current configuration state.\n        The view will be called when Pyramid or application code raises an\n        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a\n        view cannot be found for the request).  The simplest example is:\n\n          .. code-block:: python\n\n            def notfound(request):\n                return Response('Not Found', status='404 Not Found')\n\n            config.add_notfound_view(notfound)\n\n        If ``view`` argument is not provided, the view callable defaults to\n        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.\n\n        All arguments except ``append_slash`` have the same meaning as\n        :meth:`pyramid.config.Configurator.add_view` and each predicate\n        argument restricts the set of circumstances under which this notfound\n        view will be invoked.  Unlike\n        :meth:`pyramid.config.Configurator.add_view`, this method will raise\n        an exception if passed ``name``, ``permission``, ``context``,\n        ``for_``, or ``http_cache`` keyword arguments.  These argument values\n        make no sense in the context of a Not Found View.\n\n        If ``append_slash`` is ``True``, when this Not Found View is invoked,\n        and the current path info does not end in a slash, the notfound logic\n        will attempt to find a :term:`route` that matches the request's path\n        info suffixed with a slash.  If such a route exists, Pyramid will\n        issue a redirect to the URL implied by the route; if it does not,\n        Pyramid will return the result of the view callable provided as\n        ``view``, as normal.\n\n        If the argument provided as ``append_slash`` is not a boolean but\n        instead implements :class:`~pyramid.interfaces.IResponse`, the\n        append_slash logic will behave as if ``append_slash=True`` was passed,\n        but the provided class will be used as the response class instead of\n        the default :class:`~pyramid.httpexceptions.HTTPFound` response class\n        when a redirect is performed.  For example:\n\n          .. code-block:: python\n\n            from pyramid.httpexceptions import HTTPMovedPermanently\n            config.add_notfound_view(append_slash=HTTPMovedPermanently)\n\n        The above means that a redirect to a slash-appended route will be\n        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`\n        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will\n        be used` for the redirect response if a slash-appended route is found.\n\n        .. versionchanged:: 1.6\n        .. versionadded:: 1.3\n        \"\"\"\n        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):\n            if arg in view_options:\n                raise ConfigurationError(\n                    '%s may not be used as an argument to add_notfound_view'\n                    % arg\n                    )\n\n        if view is None:\n            view = default_exceptionresponse_view\n\n        settings = dict(\n            view=view,\n            context=HTTPNotFound,\n            wrapper=wrapper,\n            request_type=request_type,\n            request_method=request_method,\n            request_param=request_param,\n            containment=containment,\n            xhr=xhr,\n            accept=accept,\n            header=header,\n            path_info=path_info,\n            custom_predicates=custom_predicates,\n            decorator=decorator,\n            mapper=mapper,\n            match_param=match_param,\n            route_name=route_name,\n            permission=NO_PERMISSION_REQUIRED,\n            )\n        settings.update(view_options)\n        if append_slash:\n            view = self._derive_view(view, attr=attr, renderer=renderer)\n            if IResponse.implementedBy(append_slash):\n                view = AppendSlashNotFoundViewFactory(\n                    view, redirect_class=append_slash,\n                )\n            else:\n                view = AppendSlashNotFoundViewFactory(view)\n            settings['view'] = view\n        else:\n            settings['attr'] = attr\n            settings['renderer'] = renderer\n        return self.add_view(**settings)\n\n    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias\n\n    @action_method\n    def set_view_mapper(self, mapper):\n        \"\"\"\n        Setting a :term:`view mapper` makes it possible to make use of\n        :term:`view callable` objects which implement different call\n        signatures than the ones supported by :app:`Pyramid` as described in\n        its narrative documentation.\n\n        The ``mapper`` argument should be an object implementing\n        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted\n        Python name` to such an object.  The provided ``mapper`` will become\n        the default view mapper to be used by all subsequent :term:`view\n        configuration` registrations.\n\n        .. seealso::\n\n            See also :ref:`using_a_view_mapper`.\n\n        .. note::\n\n           Using the ``default_view_mapper`` argument to the\n           :class:`pyramid.config.Configurator` constructor\n           can be used to achieve the same purpose.\n        \"\"\"\n        mapper = self.maybe_dotted(mapper)\n        def register():\n            self.registry.registerUtility(mapper, IViewMapperFactory)\n        # IViewMapperFactory is looked up as the result of view config\n        # in phase 3\n        intr = self.introspectable('view mappers',\n                                   IViewMapperFactory,\n                                   self.object_description(mapper),\n                                   'default view mapper')\n        intr['mapper'] = mapper\n        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,\n                    introspectables=(intr,))\n\n    @action_method\n    def add_static_view(self, name, path, **kw):\n        \"\"\" Add a view used to render static assets such as images\n        and CSS files.\n\n        The ``name`` argument is a string representing an\n        application-relative local URL prefix.  It may alternately be a full\n        URL.\n\n        The ``path`` argument is the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cache_max_age`` keyword argument is input to set the\n        ``Expires`` and ``Cache-Control`` headers for static assets served.\n        Note that this argument has no effect when the ``name`` is a *url\n        prefix*.  By default, this argument is ``None``, meaning that no\n        particular Expires or Cache-Control headers are set in the response.\n\n        The ``permission`` keyword argument is used to specify the\n        :term:`permission` required by a user to execute the static view.  By\n        default, it is the string\n        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel\n        which indicates that, even if a :term:`default permission` exists for\n        the current application, the static view should be renderered to\n        completely anonymous users.  This default value is permissive\n        because, in most web apps, static assets seldom need protection from\n        viewing.  If ``permission`` is specified, the security checking will\n        be performed against the default root factory ACL.\n\n        Any other keyword arguments sent to ``add_static_view`` are passed on\n        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,\n        perhaps to define a custom factory with a custom ACL for this static\n        view).\n\n        *Usage*\n\n        The ``add_static_view`` function is typically used in conjunction\n        with the :meth:`pyramid.request.Request.static_url` method.\n        ``add_static_view`` adds a view which renders a static asset when\n        some URL is visited; :meth:`pyramid.request.Request.static_url`\n        generates a URL to that asset.\n\n        The ``name`` argument to ``add_static_view`` is usually a simple URL\n        prefix (e.g. ``'images'``).  When this is the case, the\n        :meth:`pyramid.request.Request.static_url` API will generate a URL\n        which points to a Pyramid view, which will serve up a set of assets\n        that live in the package itself. For example:\n\n        .. code-block:: python\n\n           add_static_view('images', 'mypackage:images/')\n\n        Code that registers such a view can generate URLs to the view via\n        :meth:`pyramid.request.Request.static_url`:\n\n        .. code-block:: python\n\n           request.static_url('mypackage:images/logo.png')\n\n        When ``add_static_view`` is called with a ``name`` argument that\n        represents a URL prefix, as it is above, subsequent calls to\n        :meth:`pyramid.request.Request.static_url` with paths that start with\n        the ``path`` argument passed to ``add_static_view`` will generate a\n        URL something like ``http://<Pyramid app URL>/images/logo.png``,\n        which will cause the ``logo.png`` file in the ``images`` subdirectory\n        of the ``mypackage`` package to be served.\n\n        ``add_static_view`` can alternately be used with a ``name`` argument\n        which is a *URL*, causing static assets to be served from an external\n        webserver.  This happens when the ``name`` argument is a fully\n        qualified URL (e.g. starts with ``http://`` or similar).  In this\n        mode, the ``name`` is used as the prefix of the full URL when\n        generating a URL using :meth:`pyramid.request.Request.static_url`.\n        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)\n        is used as the ``name`` argument, the generated URL will use the\n        protocol of the request (http or https, respectively).\n\n        For example, if ``add_static_view`` is called like so:\n\n        .. code-block:: python\n\n           add_static_view('http://example.com/images', 'mypackage:images/')\n\n        Subsequently, the URLs generated by\n        :meth:`pyramid.request.Request.static_url` for that static view will\n        be prefixed with ``http://example.com/images`` (the external webserver\n        listening on ``example.com`` must be itself configured to respond\n        properly to such a request.):\n\n        .. code-block:: python\n\n           static_url('mypackage:images/logo.png', request)\n\n        See :ref:`static_assets_section` for more information.\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add(self, name, spec, **kw)\n\n    def add_cache_buster(self, path, cachebust, explicit=False):\n        \"\"\"\n        Add a cache buster to a set of files on disk.\n\n        The ``path`` should be the path on disk where the static files\n        reside.  This can be an absolute path, a package-relative path, or a\n        :term:`asset specification`.\n\n        The ``cachebust`` argument may be set to cause\n        :meth:`~pyramid.request.Request.static_url` to use cache busting when\n        generating URLs. See :ref:`cache_busting` for general information\n        about cache busting. The value of the ``cachebust`` argument must\n        be an object which implements\n        :class:`~pyramid.interfaces.ICacheBuster`.\n\n        If ``explicit`` is set to ``True`` then the ``path`` for the cache\n        buster will be matched based on the ``rawspec`` instead of the\n        ``pathspec`` as defined in the\n        :class:`~pyramid.interfaces.ICacheBuster` interface.\n        Default: ``False``.\n\n        \"\"\"\n        spec = self._make_spec(path)\n        info = self._get_static_info()\n        info.add_cache_buster(self, spec, cachebust, explicit=explicit)\n\n    def _get_static_info(self):\n        info = self.registry.queryUtility(IStaticURLInfo)\n        if info is None:\n            info = StaticURLInfo()\n            self.registry.registerUtility(info, IStaticURLInfo)\n        return info\n\ndef isexception(o):\n    if IInterface.providedBy(o):\n        if IException.isEqualOrExtendedBy(o):\n            return True\n    return (\n        isinstance(o, Exception) or\n        (inspect.isclass(o) and (issubclass(o, Exception)))\n        )\n\n@implementer(IViewDeriverInfo)\nclass ViewDeriverInfo(object):\n    def __init__(self, view, registry, package, predicates, options):\n        self.original_view = view\n        self.registry = registry\n        self.package = package\n        self.predicates = predicates or []\n        self.options = options or {}\n\n    @reify\n    def settings(self):\n        return self.registry.settings\n\n@implementer(IStaticURLInfo)\nclass StaticURLInfo(object):\n    def __init__(self):\n        self.registrations = []\n        self.cache_busters = []\n\n    def generate(self, path, request, **kw):\n        for (url, spec, route_name) in self.registrations:\n            if path.startswith(spec):\n                subpath = path[len(spec):]\n                if WIN: # pragma: no cover\n                    subpath = subpath.replace('\\\\', '/') # windows\n                if self.cache_busters:\n                    subpath, kw = self._bust_asset_path(\n                        request, spec, subpath, kw)\n                if url is None:\n                    kw['subpath'] = subpath\n                    return request.route_url(route_name, **kw)\n                else:\n                    app_url, scheme, host, port, qs, anchor = \\\n                        parse_url_overrides(kw)\n                    parsed = url_parse(url)\n                    if not parsed.scheme:\n                        url = urlparse.urlunparse(parsed._replace(\n                            scheme=request.environ['wsgi.url_scheme']))\n                    subpath = url_quote(subpath)\n                    result = urljoin(url, subpath)\n                    return result + qs + anchor\n\n        raise ValueError('No static URL definition matching %s' % path)\n\n    def add(self, config, name, spec, **extra):\n        # This feature only allows for the serving of a directory and\n        # the files contained within, not of a single asset;\n        # appending a slash here if the spec doesn't have one is\n        # required for proper prefix matching done in ``generate``\n        # (``subpath = path[len(spec):]``).\n        if os.path.isabs(spec): # FBO windows\n            sep = os.sep\n        else:\n            sep = '/'\n        if not spec.endswith(sep) and not spec.endswith(':'):\n            spec = spec + sep\n\n        # we also make sure the name ends with a slash, purely as a\n        # convenience: a name that is a url is required to end in a\n        # slash, so that ``urljoin(name, subpath))`` will work above\n        # when the name is a URL, and it doesn't hurt things for it to\n        # have a name that ends in a slash if it's used as a route\n        # name instead of a URL.\n        if not name.endswith('/'):\n            # make sure it ends with a slash\n            name = name + '/'\n\n        if url_parse(name).netloc:\n            # it's a URL\n            # url, spec, route_name\n            url = name\n            route_name = None\n        else:\n            # it's a view name\n            url = None\n            cache_max_age = extra.pop('cache_max_age', None)\n\n            # create a view\n            view = static_view(spec, cache_max_age=cache_max_age,\n                               use_subpath=True)\n\n            # Mutate extra to allow factory, etc to be passed through here.\n            # Treat permission specially because we'd like to default to\n            # permissiveness (see docs of config.add_static_view).\n            permission = extra.pop('permission', None)\n            if permission is None:\n                permission = NO_PERMISSION_REQUIRED\n\n            context = extra.pop('context', None)\n            if context is None:\n                context = extra.pop('for_', None)\n\n            renderer = extra.pop('renderer', None)\n\n            # register a route using the computed view, permission, and\n            # pattern, plus any extras passed to us via add_static_view\n            pattern = \"%s*subpath\" % name # name already ends with slash\n            if config.route_prefix:\n                route_name = '__%s/%s' % (config.route_prefix, name)\n            else:\n                route_name = '__%s' % name\n            config.add_route(route_name, pattern, **extra)\n            config.add_view(\n                route_name=route_name,\n                view=view,\n                permission=permission,\n                context=context,\n                renderer=renderer,\n            )\n\n        def register():\n            registrations = self.registrations\n\n            names = [t[0] for t in registrations]\n\n            if name in names:\n                idx = names.index(name)\n                registrations.pop(idx)\n\n            # url, spec, route_name\n            registrations.append((url, spec, route_name))\n\n        intr = config.introspectable('static views',\n                                     name,\n                                     'static view for %r' % name,\n                                     'static view')\n        intr['name'] = name\n        intr['spec'] = spec\n\n        config.action(None, callable=register, introspectables=(intr,))\n\n    def add_cache_buster(self, config, spec, cachebust, explicit=False):\n        # ensure the spec always has a trailing slash as we only support\n        # adding cache busters to folders, not files\n        if os.path.isabs(spec): # FBO windows\n            sep = os.sep\n        else:\n            sep = '/'\n        if not spec.endswith(sep) and not spec.endswith(':'):\n            spec = spec + sep\n\n        def register():\n            if config.registry.settings.get('pyramid.prevent_cachebust'):\n                return\n\n            cache_busters = self.cache_busters\n\n            # find duplicate cache buster (old_idx)\n            # and insertion location (new_idx)\n            new_idx, old_idx = len(cache_busters), None\n            for idx, (spec_, cb_, explicit_) in enumerate(cache_busters):\n                # if we find an identical (spec, explicit) then use it\n                if spec == spec_ and explicit == explicit_:\n                    old_idx = new_idx = idx\n                    break\n\n                # past all explicit==False specs then add to the end\n                elif not explicit and explicit_:\n                    new_idx = idx\n                    break\n\n                # explicit matches and spec is shorter\n                elif explicit == explicit_ and len(spec) < len(spec_):\n                    new_idx = idx\n                    break\n\n            if old_idx is not None:\n                cache_busters.pop(old_idx)\n\n            cache_busters.insert(new_idx, (spec, cachebust, explicit))\n\n        intr = config.introspectable('cache busters',\n                                     spec,\n                                     'cache buster for %r' % spec,\n                                     'cache buster')\n        intr['cachebust'] = cachebust\n        intr['path'] = spec\n        intr['explicit'] = explicit\n\n        config.action(None, callable=register, introspectables=(intr,))\n\n    def _bust_asset_path(self, request, spec, subpath, kw):\n        registry = request.registry\n        pkg_name, pkg_subpath = resolve_asset_spec(spec)\n        rawspec = None\n\n        if pkg_name is not None:\n            pathspec = '{0}:{1}{2}'.format(pkg_name, pkg_subpath, subpath)\n            overrides = registry.queryUtility(IPackageOverrides, name=pkg_name)\n            if overrides is not None:\n                resource_name = posixpath.join(pkg_subpath, subpath)\n                sources = overrides.filtered_sources(resource_name)\n                for source, filtered_path in sources:\n                    rawspec = source.get_path(filtered_path)\n                    if hasattr(source, 'pkg_name'):\n                        rawspec = '{0}:{1}'.format(source.pkg_name, rawspec)\n                    break\n\n        else:\n            pathspec = pkg_subpath + subpath\n\n        if rawspec is None:\n            rawspec = pathspec\n\n        kw['pathspec'] = pathspec\n        kw['rawspec'] = rawspec\n        for spec_, cachebust, explicit in reversed(self.cache_busters):\n            if (\n                (explicit and rawspec.startswith(spec_)) or\n                (not explicit and pathspec.startswith(spec_))\n            ):\n                subpath, kw = cachebust(request, subpath, kw)\n                break\n        return subpath, kw\n", "pyramid/viewderivers.py": "import inspect\n\nfrom zope.interface import (\n    implementer,\n    provider,\n    )\n\nfrom pyramid.security import NO_PERMISSION_REQUIRED\nfrom pyramid.response import Response\n\nfrom pyramid.interfaces import (\n    IAuthenticationPolicy,\n    IAuthorizationPolicy,\n    IDebugLogger,\n    IResponse,\n    IViewMapper,\n    IViewMapperFactory,\n    )\n\nfrom pyramid.compat import (\n    is_bound_method,\n    is_unbound_method,\n    )\n\nfrom pyramid.config.util import (\n    DEFAULT_PHASH,\n    MAX_ORDER,\n    takes_one_arg,\n    )\n\nfrom pyramid.exceptions import (\n    ConfigurationError,\n    PredicateMismatch,\n    )\nfrom pyramid.httpexceptions import HTTPForbidden\nfrom pyramid.util import object_description\nfrom pyramid.view import render_view_to_response\nfrom pyramid import renderers\n\n\ndef view_description(view):\n    try:\n        return view.__text__\n    except AttributeError:\n        # custom view mappers might not add __text__\n        return object_description(view)\n\ndef requestonly(view, attr=None):\n    return takes_one_arg(view, attr=attr, argname='request')\n\n@implementer(IViewMapper)\n@provider(IViewMapperFactory)\nclass DefaultViewMapper(object):\n    def __init__(self, **kw):\n        self.attr = kw.get('attr')\n\n    def __call__(self, view):\n        if is_unbound_method(view) and self.attr is None:\n            raise ConfigurationError((\n                'Unbound method calls are not supported, please set the class '\n                'as your `view` and the method as your `attr`'\n            ))\n\n        if inspect.isclass(view):\n            view = self.map_class(view)\n        else:\n            view = self.map_nonclass(view)\n        return view\n\n    def map_class(self, view):\n        ronly = requestonly(view, self.attr)\n        if ronly:\n            mapped_view = self.map_class_requestonly(view)\n        else:\n            mapped_view = self.map_class_native(view)\n        mapped_view.__text__ = 'method %s of %s' % (\n            self.attr or '__call__', object_description(view))\n        return mapped_view\n\n    def map_nonclass(self, view):\n        # We do more work here than appears necessary to avoid wrapping the\n        # view unless it actually requires wrapping (to avoid function call\n        # overhead).\n        mapped_view = view\n        ronly = requestonly(view, self.attr)\n        if ronly:\n            mapped_view = self.map_nonclass_requestonly(view)\n        elif self.attr:\n            mapped_view = self.map_nonclass_attr(view)\n        if inspect.isroutine(mapped_view):\n            # This branch will be true if the view is a function or a method.\n            # We potentially mutate an unwrapped object here if it's a\n            # function.  We do this to avoid function call overhead of\n            # injecting another wrapper.  However, we must wrap if the\n            # function is a bound method because we can't set attributes on a\n            # bound method.\n            if is_bound_method(view):\n                _mapped_view = mapped_view\n                def mapped_view(context, request):\n                    return _mapped_view(context, request)\n            if self.attr is not None:\n                mapped_view.__text__ = 'attr %s of %s' % (\n                    self.attr, object_description(view))\n            else:\n                mapped_view.__text__ = object_description(view)\n        return mapped_view\n\n    def map_class_requestonly(self, view):\n        # its a class that has an __init__ which only accepts request\n        attr = self.attr\n        def _class_requestonly_view(context, request):\n            inst = view(request)\n            request.__view__ = inst\n            if attr is None:\n                response = inst()\n            else:\n                response = getattr(inst, attr)()\n            return response\n        return _class_requestonly_view\n\n    def map_class_native(self, view):\n        # its a class that has an __init__ which accepts both context and\n        # request\n        attr = self.attr\n        def _class_view(context, request):\n            inst = view(context, request)\n            request.__view__ = inst\n            if attr is None:\n                response = inst()\n            else:\n                response = getattr(inst, attr)()\n            return response\n        return _class_view\n\n    def map_nonclass_requestonly(self, view):\n        # its a function that has a __call__ which accepts only a single\n        # request argument\n        attr = self.attr\n        def _requestonly_view(context, request):\n            if attr is None:\n                response = view(request)\n            else:\n                response = getattr(view, attr)(request)\n            return response\n        return _requestonly_view\n\n    def map_nonclass_attr(self, view):\n        # its a function that has a __call__ which accepts both context and\n        # request, but still has an attr\n        def _attr_view(context, request):\n            response = getattr(view, self.attr)(context, request)\n            return response\n        return _attr_view\n\n\ndef wraps_view(wrapper):\n    def inner(view, info):\n        wrapper_view = wrapper(view, info)\n        return preserve_view_attrs(view, wrapper_view)\n    return inner\n\ndef preserve_view_attrs(view, wrapper):\n    if view is None:\n        return wrapper\n\n    if wrapper is view:\n        return view\n\n    original_view = getattr(view, '__original_view__', None)\n\n    if original_view is None:\n        original_view = view\n\n    wrapper.__wraps__ = view\n    wrapper.__original_view__ = original_view\n    wrapper.__module__ = view.__module__\n    wrapper.__doc__ = view.__doc__\n\n    try:\n        wrapper.__name__ = view.__name__\n    except AttributeError:\n        wrapper.__name__ = repr(view)\n\n    # attrs that may not exist on \"view\", but, if so, must be attached to\n    # \"wrapped view\"\n    for attr in ('__permitted__', '__call_permissive__', '__permission__',\n                 '__predicated__', '__predicates__', '__accept__',\n                 '__order__', '__text__'):\n        try:\n            setattr(wrapper, attr, getattr(view, attr))\n        except AttributeError:\n            pass\n\n    return wrapper\n\ndef mapped_view(view, info):\n    mapper = info.options.get('mapper')\n    if mapper is None:\n        mapper = getattr(view, '__view_mapper__', None)\n        if mapper is None:\n            mapper = info.registry.queryUtility(IViewMapperFactory)\n            if mapper is None:\n                mapper = DefaultViewMapper\n\n    mapped_view = mapper(**info.options)(view)\n    return mapped_view\n\nmapped_view.options = ('mapper', 'attr')\n\ndef owrapped_view(view, info):\n    wrapper_viewname = info.options.get('wrapper')\n    viewname = info.options.get('name')\n    if not wrapper_viewname:\n        return view\n    def _owrapped_view(context, request):\n        response = view(context, request)\n        request.wrapped_response = response\n        request.wrapped_body = response.body\n        request.wrapped_view = view\n        wrapped_response = render_view_to_response(context, request,\n                                                   wrapper_viewname)\n        if wrapped_response is None:\n            raise ValueError(\n                'No wrapper view named %r found when executing view '\n                'named %r' % (wrapper_viewname, viewname))\n        return wrapped_response\n    return _owrapped_view\n\nowrapped_view.options = ('name', 'wrapper')\n\ndef http_cached_view(view, info):\n    if info.settings.get('prevent_http_cache', False):\n        return view\n\n    seconds = info.options.get('http_cache')\n\n    if seconds is None:\n        return view\n\n    options = {}\n\n    if isinstance(seconds, (tuple, list)):\n        try:\n            seconds, options = seconds\n        except ValueError:\n            raise ConfigurationError(\n                'If http_cache parameter is a tuple or list, it must be '\n                'in the form (seconds, options); not %s' % (seconds,))\n\n    def wrapper(context, request):\n        response = view(context, request)\n        prevent_caching = getattr(response.cache_control, 'prevent_auto',\n                                  False)\n        if not prevent_caching:\n            response.cache_expires(seconds, **options)\n        return response\n\n    return wrapper\n\nhttp_cached_view.options = ('http_cache',)\n\ndef secured_view(view, info):\n    for wrapper in (_secured_view, _authdebug_view):\n        view = wraps_view(wrapper)(view, info)\n    return view\n\nsecured_view.options = ('permission',)\n\ndef _secured_view(view, info):\n    permission = info.options.get('permission')\n    if permission == NO_PERMISSION_REQUIRED:\n        # allow views registered within configurations that have a\n        # default permission to explicitly override the default\n        # permission, replacing it with no permission at all\n        permission = None\n\n    wrapped_view = view\n    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)\n    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)\n\n    if authn_policy and authz_policy and (permission is not None):\n        def _permitted(context, request):\n            principals = authn_policy.effective_principals(request)\n            return authz_policy.permits(context, principals, permission)\n        def _secured_view(context, request):\n            result = _permitted(context, request)\n            if result:\n                return view(context, request)\n            view_name = getattr(view, '__name__', view)\n            msg = getattr(\n                request, 'authdebug_message',\n                'Unauthorized: %s failed permission check' % view_name)\n            raise HTTPForbidden(msg, result=result)\n        _secured_view.__call_permissive__ = view\n        _secured_view.__permitted__ = _permitted\n        _secured_view.__permission__ = permission\n        wrapped_view = _secured_view\n\n    return wrapped_view\n\ndef _authdebug_view(view, info):\n    wrapped_view = view\n    settings = info.settings\n    permission = info.options.get('permission')\n    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)\n    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)\n    logger = info.registry.queryUtility(IDebugLogger)\n    if settings and settings.get('debug_authorization', False):\n        def _authdebug_view(context, request):\n            view_name = getattr(request, 'view_name', None)\n\n            if authn_policy and authz_policy:\n                if permission is NO_PERMISSION_REQUIRED:\n                    msg = 'Allowed (NO_PERMISSION_REQUIRED)'\n                elif permission is None:\n                    msg = 'Allowed (no permission registered)'\n                else:\n                    principals = authn_policy.effective_principals(request)\n                    msg = str(authz_policy.permits(\n                        context, principals, permission))\n            else:\n                msg = 'Allowed (no authorization policy in use)'\n\n            view_name = getattr(request, 'view_name', None)\n            url = getattr(request, 'url', None)\n            msg = ('debug_authorization of url %s (view name %r against '\n                   'context %r): %s' % (url, view_name, context, msg))\n            if logger:\n                logger.debug(msg)\n            if request is not None:\n                request.authdebug_message = msg\n            return view(context, request)\n\n        wrapped_view = _authdebug_view\n\n    return wrapped_view\n\ndef predicated_view(view, info):\n    preds = info.predicates\n    if not preds:\n        return view\n    def predicate_wrapper(context, request):\n        for predicate in preds:\n            if not predicate(context, request):\n                view_name = getattr(view, '__name__', view)\n                raise PredicateMismatch(\n                    'predicate mismatch for view %s (%s)' % (\n                        view_name, predicate.text()))\n        return view(context, request)\n    def checker(context, request):\n        return all((predicate(context, request) for predicate in\n                    preds))\n    predicate_wrapper.__predicated__ = checker\n    predicate_wrapper.__predicates__ = preds\n    return predicate_wrapper\n\ndef attr_wrapped_view(view, info):\n    accept, order, phash = (info.options.get('accept', None),\n                            getattr(info, 'order', MAX_ORDER),\n                            getattr(info, 'phash', DEFAULT_PHASH))\n    # this is a little silly but we don't want to decorate the original\n    # function with attributes that indicate accept, order, and phash,\n    # so we use a wrapper\n    if (\n        (accept is None) and\n        (order == MAX_ORDER) and\n        (phash == DEFAULT_PHASH)\n    ):\n        return view # defaults\n    def attr_view(context, request):\n        return view(context, request)\n    attr_view.__accept__ = accept\n    attr_view.__order__ = order\n    attr_view.__phash__ = phash\n    attr_view.__view_attr__ = info.options.get('attr')\n    attr_view.__permission__ = info.options.get('permission')\n    return attr_view\n\nattr_wrapped_view.options = ('accept', 'attr', 'permission')\n\ndef rendered_view(view, info):\n    # one way or another this wrapper must produce a Response (unless\n    # the renderer is a NullRendererHelper)\n    renderer = info.options.get('renderer')\n    if renderer is None:\n        # register a default renderer if you want super-dynamic\n        # rendering.  registering a default renderer will also allow\n        # override_renderer to work if a renderer is left unspecified for\n        # a view registration.\n        def viewresult_to_response(context, request):\n            result = view(context, request)\n            if result.__class__ is Response: # common case\n                response = result\n            else:\n                response = info.registry.queryAdapterOrSelf(result, IResponse)\n                if response is None:\n                    if result is None:\n                        append = (' You may have forgotten to return a value '\n                                  'from the view callable.')\n                    elif isinstance(result, dict):\n                        append = (' You may have forgotten to define a '\n                                  'renderer in the view configuration.')\n                    else:\n                        append = ''\n\n                    msg = ('Could not convert return value of the view '\n                           'callable %s into a response object. '\n                           'The value returned was %r.' + append)\n\n                    raise ValueError(msg % (view_description(view), result))\n\n            return response\n\n        return viewresult_to_response\n\n    if renderer is renderers.null_renderer:\n        return view\n\n    def rendered_view(context, request):\n        result = view(context, request)\n        if result.__class__ is Response: # potential common case\n            response = result\n        else:\n            # this must adapt, it can't do a simple interface check\n            # (avoid trying to render webob responses)\n            response = info.registry.queryAdapterOrSelf(result, IResponse)\n            if response is None:\n                attrs = getattr(request, '__dict__', {})\n                if 'override_renderer' in attrs:\n                    # renderer overridden by newrequest event or other\n                    renderer_name = attrs.pop('override_renderer')\n                    view_renderer = renderers.RendererHelper(\n                        name=renderer_name,\n                        package=info.package,\n                        registry=info.registry)\n                else:\n                    view_renderer = renderer.clone()\n                if '__view__' in attrs:\n                    view_inst = attrs.pop('__view__')\n                else:\n                    view_inst = getattr(view, '__original_view__', view)\n                response = view_renderer.render_view(\n                    request, result, view_inst, context)\n        return response\n\n    return rendered_view\n\nrendered_view.options = ('renderer',)\n\ndef decorated_view(view, info):\n    decorator = info.options.get('decorator')\n    if decorator is None:\n        return view\n    return decorator(view)\n\ndecorated_view.options = ('decorator',)\n\nMAPPED_VIEW = 'mapped_view'\nINGRESS = 'INGRESS'\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
### ImportError: Cannot Import 'VIEW' from 'pyramid.viewderivers'

#### Description
After updating the constraints for view derivers, attempting to import the `VIEW` constant from `pyramid.viewderivers` results in an `ImportError`. This prevents certain tests from running successfully and disrupts the configuration of view derivers.

#### Example Code
```python
from pyramid.viewderivers import VIEW

def test_add_deriver_enforces_view_is_last():
    from pyramid.exceptions import ConfigurationError

    def deriv1(view, info): pass
    try:
        config.add_view_deriver(deriv1, under=VIEW)
    except ConfigurationError as ex:
        assert 'cannot be under VIEW' in ex.args[0]
    else:
        raise AssertionError
```

#### Expected Behavior
The `VIEW` constant should be successfully imported from `pyramid.viewderivers`, allowing tests and configurations that rely on it to function correctly.

#### Actual Behavior
An `ImportError` is raised:
```
ImportError: cannot import name 'VIEW' from 'pyramid.viewderivers' (/path/to/pyramid/viewderivers.py)
```

This error indicates that the `VIEW` constant is either not defined or not properly exposed in the `pyramid.viewderivers` module after the recent commit.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### pyramid/viewderivers.py
import inspect

from zope.interface import (
    implementer,
    provider,
    )

from pyramid.security import NO_PERMISSION_REQUIRED
from pyramid.response import Response

from pyramid.interfaces import (
    IAuthenticationPolicy,
    IAuthorizationPolicy,
    IDebugLogger,
    IResponse,
    IViewMapper,
    IViewMapperFactory,
    )

from pyramid.compat import (
    is_bound_method,
    is_unbound_method,
    )

from pyramid.config.util import (
    DEFAULT_PHASH,
    MAX_ORDER,
    takes_one_arg,
    )

from pyramid.exceptions import (
    ConfigurationError,
    PredicateMismatch,
    )
from pyramid.httpexceptions import HTTPForbidden
from pyramid.util import object_description
from pyramid.view import render_view_to_response
from pyramid import renderers


def view_description(view):
    try:
        return view.__text__
    except AttributeError:
        # custom view mappers might not add __text__
        return object_description(view)

def requestonly(view, attr=None):
    return takes_one_arg(view, attr=attr, argname='request')

@implementer(IViewMapper)
@provider(IViewMapperFactory)
class DefaultViewMapper(object):
    def __init__(self, **kw):
        self.attr = kw.get('attr')

    def __call__(self, view):
        if is_unbound_method(view) and self.attr is None:
            raise ConfigurationError((
                'Unbound method calls are not supported, please set the class '
                'as your `view` and the method as your `attr`'
            ))

        if inspect.isclass(view):
            view = self.map_class(view)
        else:
            view = self.map_nonclass(view)
        return view

    def map_class(self, view):
        ronly = requestonly(view, self.attr)
        if ronly:
            mapped_view = self.map_class_requestonly(view)
        else:
            mapped_view = self.map_class_native(view)
        mapped_view.__text__ = 'method %s of %s' % (
            self.attr or '__call__', object_description(view))
        return mapped_view

    def map_nonclass(self, view):
        # We do more work here than appears necessary to avoid wrapping the
        # view unless it actually requires wrapping (to avoid function call
        # overhead).
        mapped_view = view
        ronly = requestonly(view, self.attr)
        if ronly:
            mapped_view = self.map_nonclass_requestonly(view)
        elif self.attr:
            mapped_view = self.map_nonclass_attr(view)
        if inspect.isroutine(mapped_view):
            # This branch will be true if the view is a function or a method.
            # We potentially mutate an unwrapped object here if it's a
            # function.  We do this to avoid function call overhead of
            # injecting another wrapper.  However, we must wrap if the
            # function is a bound method because we can't set attributes on a
            # bound method.
            if is_bound_method(view):
                _mapped_view = mapped_view
                def mapped_view(context, request):
                    return _mapped_view(context, request)
            if self.attr is not None:
                mapped_view.__text__ = 'attr %s of %s' % (
                    self.attr, object_description(view))
            else:
                mapped_view.__text__ = object_description(view)
        return mapped_view

    def map_class_requestonly(self, view):
        # its a class that has an __init__ which only accepts request
        attr = self.attr
        def _class_requestonly_view(context, request):
            inst = view(request)
            request.__view__ = inst
            if attr is None:
                response = inst()
            else:
                response = getattr(inst, attr)()
            return response
        return _class_requestonly_view

    def map_class_native(self, view):
        # its a class that has an __init__ which accepts both context and
        # request
        attr = self.attr
        def _class_view(context, request):
            inst = view(context, request)
            request.__view__ = inst
            if attr is None:
                response = inst()
            else:
                response = getattr(inst, attr)()
            return response
        return _class_view

    def map_nonclass_requestonly(self, view):
        # its a function that has a __call__ which accepts only a single
        # request argument
        attr = self.attr
        def _requestonly_view(context, request):
            if attr is None:
                response = view(request)
            else:
                response = getattr(view, attr)(request)
            return response
        return _requestonly_view

    def map_nonclass_attr(self, view):
        # its a function that has a __call__ which accepts both context and
        # request, but still has an attr
        def _attr_view(context, request):
            response = getattr(view, self.attr)(context, request)
            return response
        return _attr_view


def wraps_view(wrapper):
    def inner(view, info):
        wrapper_view = wrapper(view, info)
        return preserve_view_attrs(view, wrapper_view)
    return inner

def preserve_view_attrs(view, wrapper):
    if view is None:
        return wrapper

    if wrapper is view:
        return view

    original_view = getattr(view, '__original_view__', None)

    if original_view is None:
        original_view = view

    wrapper.__wraps__ = view
    wrapper.__original_view__ = original_view
    wrapper.__module__ = view.__module__
    wrapper.__doc__ = view.__doc__

    try:
        wrapper.__name__ = view.__name__
    except AttributeError:
        wrapper.__name__ = repr(view)

    # attrs that may not exist on "view", but, if so, must be attached to
    # "wrapped view"
    for attr in ('__permitted__', '__call_permissive__', '__permission__',
                 '__predicated__', '__predicates__', '__accept__',
                 '__order__', '__text__'):
        try:
            setattr(wrapper, attr, getattr(view, attr))
        except AttributeError:
            pass

    return wrapper

def mapped_view(view, info):
    mapper = info.options.get('mapper')
    if mapper is None:
        mapper = getattr(view, '__view_mapper__', None)
        if mapper is None:
            mapper = info.registry.queryUtility(IViewMapperFactory)
            if mapper is None:
                mapper = DefaultViewMapper

    mapped_view = mapper(**info.options)(view)
    return mapped_view

mapped_view.options = ('mapper', 'attr')

def owrapped_view(view, info):
    wrapper_viewname = info.options.get('wrapper')
    viewname = info.options.get('name')
    if not wrapper_viewname:
        return view
    def _owrapped_view(context, request):
        response = view(context, request)
        request.wrapped_response = response
        request.wrapped_body = response.body
        request.wrapped_view = view
        wrapped_response = render_view_to_response(context, request,
                                                   wrapper_viewname)
        if wrapped_response is None:
            raise ValueError(
                'No wrapper view named %r found when executing view '
                'named %r' % (wrapper_viewname, viewname))
        return wrapped_response
    return _owrapped_view

owrapped_view.options = ('name', 'wrapper')

def http_cached_view(view, info):
    if info.settings.get('prevent_http_cache', False):
        return view

    seconds = info.options.get('http_cache')

    if seconds is None:
        return view

    options = {}

    if isinstance(seconds, (tuple, list)):
        try:
            seconds, options = seconds
        except ValueError:
            raise ConfigurationError(
                'If http_cache parameter is a tuple or list, it must be '
                'in the form (seconds, options); not %s' % (seconds,))

    def wrapper(context, request):
        response = view(context, request)
        prevent_caching = getattr(response.cache_control, 'prevent_auto',
                                  False)
        if not prevent_caching:
            response.cache_expires(seconds, **options)
        return response

    return wrapper

http_cached_view.options = ('http_cache',)

def secured_view(view, info):
    for wrapper in (_secured_view, _authdebug_view):
        view = wraps_view(wrapper)(view, info)
    return view

secured_view.options = ('permission',)

def _secured_view(view, info):
    permission = info.options.get('permission')
    if permission == NO_PERMISSION_REQUIRED:
        # allow views registered within configurations that have a
        # default permission to explicitly override the default
        # permission, replacing it with no permission at all
        permission = None

    wrapped_view = view
    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)
    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)

    if authn_policy and authz_policy and (permission is not None):
        def _permitted(context, request):
            principals = authn_policy.effective_principals(request)
            return authz_policy.permits(context, principals, permission)
        def _secured_view(context, request):
            result = _permitted(context, request)
            if result:
                return view(context, request)
            view_name = getattr(view, '__name__', view)
            msg = getattr(
                request, 'authdebug_message',
                'Unauthorized: %s failed permission check' % view_name)
            raise HTTPForbidden(msg, result=result)
        _secured_view.__call_permissive__ = view
        _secured_view.__permitted__ = _permitted
        _secured_view.__permission__ = permission
        wrapped_view = _secured_view

    return wrapped_view

def _authdebug_view(view, info):
    wrapped_view = view
    settings = info.settings
    permission = info.options.get('permission')
    authn_policy = info.registry.queryUtility(IAuthenticationPolicy)
    authz_policy = info.registry.queryUtility(IAuthorizationPolicy)
    logger = info.registry.queryUtility(IDebugLogger)
    if settings and settings.get('debug_authorization', False):
        def _authdebug_view(context, request):
            view_name = getattr(request, 'view_name', None)

            if authn_policy and authz_policy:
                if permission is NO_PERMISSION_REQUIRED:
                    msg = 'Allowed (NO_PERMISSION_REQUIRED)'
                elif permission is None:
                    msg = 'Allowed (no permission registered)'
                else:
                    principals = authn_policy.effective_principals(request)
                    msg = str(authz_policy.permits(
                        context, principals, permission))
            else:
                msg = 'Allowed (no authorization policy in use)'

            view_name = getattr(request, 'view_name', None)
            url = getattr(request, 'url', None)
            msg = ('debug_authorization of url %s (view name %r against '
                   'context %r): %s' % (url, view_name, context, msg))
            if logger:
                logger.debug(msg)
            if request is not None:
                request.authdebug_message = msg
            return view(context, request)

        wrapped_view = _authdebug_view

    return wrapped_view

def predicated_view(view, info):
    preds = info.predicates
    if not preds:
        return view
    def predicate_wrapper(context, request):
        for predicate in preds:
            if not predicate(context, request):
                view_name = getattr(view, '__name__', view)
                raise PredicateMismatch(
                    'predicate mismatch for view %s (%s)' % (
                        view_name, predicate.text()))
        return view(context, request)
    def checker(context, request):
        return all((predicate(context, request) for predicate in
                    preds))
    predicate_wrapper.__predicated__ = checker
    predicate_wrapper.__predicates__ = preds
    return predicate_wrapper

def attr_wrapped_view(view, info):
    accept, order, phash = (info.options.get('accept', None),
                            getattr(info, 'order', MAX_ORDER),
                            getattr(info, 'phash', DEFAULT_PHASH))
    # this is a little silly but we don't want to decorate the original
    # function with attributes that indicate accept, order, and phash,
    # so we use a wrapper
    if (
        (accept is None) and
        (order == MAX_ORDER) and
        (phash == DEFAULT_PHASH)
    ):
        return view # defaults
    def attr_view(context, request):
        return view(context, request)
    attr_view.__accept__ = accept
    attr_view.__order__ = order
    attr_view.__phash__ = phash
    attr_view.__view_attr__ = info.options.get('attr')
    attr_view.__permission__ = info.options.get('permission')
    return attr_view

attr_wrapped_view.options = ('accept', 'attr', 'permission')

def rendered_view(view, info):
    # one way or another this wrapper must produce a Response (unless
    # the renderer is a NullRendererHelper)
    renderer = info.options.get('renderer')
    if renderer is None:
        # register a default renderer if you want super-dynamic
        # rendering.  registering a default renderer will also allow
        # override_renderer to work if a renderer is left unspecified for
        # a view registration.
        def viewresult_to_response(context, request):
            result = view(context, request)
            if result.__class__ is Response: # common case
                response = result
            else:
                response = info.registry.queryAdapterOrSelf(result, IResponse)
                if response is None:
                    if result is None:
                        append = (' You may have forgotten to return a value '
                                  'from the view callable.')
                    elif isinstance(result, dict):
                        append = (' You may have forgotten to define a '
                                  'renderer in the view configuration.')
                    else:
                        append = ''

                    msg = ('Could not convert return value of the view '
                           'callable %s into a response object. '
                           'The value returned was %r.' + append)

                    raise ValueError(msg % (view_description(view), result))

            return response

        return viewresult_to_response

    if renderer is renderers.null_renderer:
        return view

    def rendered_view(context, request):
        result = view(context, request)
        if result.__class__ is Response: # potential common case
            response = result
        else:
            # this must adapt, it can't do a simple interface check
            # (avoid trying to render webob responses)
            response = info.registry.queryAdapterOrSelf(result, IResponse)
            if response is None:
                attrs = getattr(request, '__dict__', {})
                if 'override_renderer' in attrs:
                    # renderer overridden by newrequest event or other
                    renderer_name = attrs.pop('override_renderer')
                    view_renderer = renderers.RendererHelper(
                        name=renderer_name,
                        package=info.package,
                        registry=info.registry)
                else:
                    view_renderer = renderer.clone()
                if '__view__' in attrs:
                    view_inst = attrs.pop('__view__')
                else:
                    view_inst = getattr(view, '__original_view__', view)
                response = view_renderer.render_view(
                    request, result, view_inst, context)
        return response

    return rendered_view

rendered_view.options = ('renderer',)

def decorated_view(view, info):
    decorator = info.options.get('decorator')
    if decorator is None:
        return view
    return decorator(view)

decorated_view.options = ('decorator',)

MAPPED_VIEW = 'mapped_view'
INGRESS = 'INGRESS'


### pyramid/config/views.py
import inspect
import posixpath
import operator
import os
import warnings

from zope.interface import (
    Interface,
    implementedBy,
    implementer,
    )

from zope.interface.interfaces import IInterface

from pyramid.interfaces import (
    IDefaultPermission,
    IException,
    IExceptionViewClassifier,
    IMultiView,
    IPackageOverrides,
    IRendererFactory,
    IRequest,
    IResponse,
    IRouteRequest,
    ISecuredView,
    IStaticURLInfo,
    IView,
    IViewClassifier,
    IViewDerivers,
    IViewDeriverInfo,
    IViewMapperFactory,
    PHASE1_CONFIG,
    )

from pyramid import renderers

from pyramid.asset import resolve_asset_spec
from pyramid.compat import (
    string_types,
    urlparse,
    url_quote,
    WIN,
    is_nonstr_iter,
    )

from pyramid.decorator import reify

from pyramid.exceptions import (
    ConfigurationError,
    PredicateMismatch,
    )

from pyramid.httpexceptions import (
    HTTPForbidden,
    HTTPNotFound,
    default_exceptionresponse_view,
    )

from pyramid.registry import (
    predvalseq,
    Deferred,
    )

from pyramid.security import NO_PERMISSION_REQUIRED
from pyramid.static import static_view

from pyramid.url import parse_url_overrides

from pyramid.view import AppendSlashNotFoundViewFactory

import pyramid.util
from pyramid.util import (
    viewdefaults,
    action_method,
    TopologicalSorter,
    )

import pyramid.config.predicates
import pyramid.viewderivers

from pyramid.viewderivers import (
    INGRESS,
    MAPPED_VIEW,
    preserve_view_attrs,
    view_description,
    requestonly,
    DefaultViewMapper,
    wraps_view,
)

from pyramid.config.util import (
    DEFAULT_PHASH,
    MAX_ORDER,
    as_sorted_tuple,
    )

urljoin = urlparse.urljoin
url_parse = urlparse.urlparse

DefaultViewMapper = DefaultViewMapper # bw-compat
preserve_view_attrs = preserve_view_attrs # bw-compat
requestonly = requestonly # bw-compat
view_description = view_description # bw-compat

@implementer(IMultiView)
class MultiView(object):

    def __init__(self, name):
        self.name = name
        self.media_views = {}
        self.views = []
        self.accepts = []

    def __discriminator__(self, context, request):
        # used by introspection systems like so:
        # view = adapters.lookup(....)
        # view.__discriminator__(context, request) -> view's discriminator
        # so that superdynamic systems can feed the discriminator to
        # the introspection system to get info about it
        view = self.match(context, request)
        return view.__discriminator__(context, request)

    def add(self, view, order, accept=None, phash=None):
        if phash is not None:
            for i, (s, v, h) in enumerate(list(self.views)):
                if phash == h:
                    self.views[i] = (order, view, phash)
                    return

        if accept is None or '*' in accept:
            self.views.append((order, view, phash))
            self.views.sort(key=operator.itemgetter(0))
        else:
            subset = self.media_views.setdefault(accept, [])
            for i, (s, v, h) in enumerate(list(subset)):
                if phash == h:
                    subset[i] = (order, view, phash)
                    return
            else:
                subset.append((order, view, phash))
                subset.sort(key=operator.itemgetter(0))
            accepts = set(self.accepts)
            accepts.add(accept)
            self.accepts = list(accepts) # dedupe

    def get_views(self, request):
        if self.accepts and hasattr(request, 'accept'):
            accepts = self.accepts[:]
            views = []
            while accepts:
                match = request.accept.best_match(accepts)
                if match is None:
                    break
                subset = self.media_views[match]
                views.extend(subset)
                accepts.remove(match)
            views.extend(self.views)
            return views
        return self.views

    def match(self, context, request):
        for order, view, phash in self.get_views(request):
            if not hasattr(view, '__predicated__'):
                return view
            if view.__predicated__(context, request):
                return view
        raise PredicateMismatch(self.name)

    def __permitted__(self, context, request):
        view = self.match(context, request)
        if hasattr(view, '__permitted__'):
            return view.__permitted__(context, request)
        return True

    def __call_permissive__(self, context, request):
        view = self.match(context, request)
        view = getattr(view, '__call_permissive__', view)
        return view(context, request)

    def __call__(self, context, request):
        for order, view, phash in self.get_views(request):
            try:
                return view(context, request)
            except PredicateMismatch:
                continue
        raise PredicateMismatch(self.name)

class ViewsConfiguratorMixin(object):
    @viewdefaults
    @action_method
    def add_view(
        self,
        view=None,
        name="",
        for_=None,
        permission=None,
        request_type=None,
        route_name=None,
        request_method=None,
        request_param=None,
        containment=None,
        attr=None,
        renderer=None,
        wrapper=None,
        xhr=None,
        accept=None,
        header=None,
        path_info=None,
        custom_predicates=(),
        context=None,
        decorator=None,
        mapper=None,
        http_cache=None,
        match_param=None,
        check_csrf=None,
        **view_options):
        """ Add a :term:`view configuration` to the current
        configuration state.  Arguments to ``add_view`` are broken
        down below into *predicate* arguments and *non-predicate*
        arguments.  Predicate arguments narrow the circumstances in
        which the view callable will be invoked when a request is
        presented to :app:`Pyramid`; non-predicate arguments are
        informational.

        Non-Predicate Arguments

        view

          A :term:`view callable` or a :term:`dotted Python name`
          which refers to a view callable.  This argument is required
          unless a ``renderer`` argument also exists.  If a
          ``renderer`` argument is passed, and a ``view`` argument is
          not provided, the view callable defaults to a callable that
          returns an empty dictionary (see
          :ref:`views_which_use_a_renderer`).

        permission

          A :term:`permission` that the user must possess in order to invoke
          the :term:`view callable`.  See :ref:`view_security_section` for
          more information about view security and permissions.  This is
          often a string like ``view`` or ``edit``.

          If ``permission`` is omitted, a *default* permission may be used
          for this view registration if one was named as the
          :class:`pyramid.config.Configurator` constructor's
          ``default_permission`` argument, or if
          :meth:`pyramid.config.Configurator.set_default_permission` was used
          prior to this view registration.  Pass the value
          :data:`pyramid.security.NO_PERMISSION_REQUIRED` as the permission
          argument to explicitly indicate that the view should always be
          executable by entirely anonymous users, regardless of the default
          permission, bypassing any :term:`authorization policy` that may be
          in effect.

        attr

          This knob is most useful when the view definition is a class.

          The view machinery defaults to using the ``__call__`` method
          of the :term:`view callable` (or the function itself, if the
          view callable is a function) to obtain a response.  The
          ``attr`` value allows you to vary the method attribute used
          to obtain the response.  For example, if your view was a
          class, and the class has a method named ``index`` and you
          wanted to use this method instead of the class' ``__call__``
          method to return the response, you'd say ``attr="index"`` in the
          view configuration for the view.

        renderer

          This is either a single string term (e.g. ``json``) or a
          string implying a path or :term:`asset specification`
          (e.g. ``templates/views.pt``) naming a :term:`renderer`
          implementation.  If the ``renderer`` value does not contain
          a dot ``.``, the specified string will be used to look up a
          renderer implementation, and that renderer implementation
          will be used to construct a response from the view return
          value.  If the ``renderer`` value contains a dot (``.``),
          the specified term will be treated as a path, and the
          filename extension of the last element in the path will be
          used to look up the renderer implementation, which will be
          passed the full path.  The renderer implementation will be
          used to construct a :term:`response` from the view return
          value.

          Note that if the view itself returns a :term:`response` (see
          :ref:`the_response`), the specified renderer implementation
          is never called.

          When the renderer is a path, although a path is usually just
          a simple relative pathname (e.g. ``templates/foo.pt``,
          implying that a template named "foo.pt" is in the
          "templates" directory relative to the directory of the
          current :term:`package` of the Configurator), a path can be
          absolute, starting with a slash on UNIX or a drive letter
          prefix on Windows.  The path can alternately be a
          :term:`asset specification` in the form
          ``some.dotted.package_name:relative/path``, making it
          possible to address template assets which live in a
          separate package.

          The ``renderer`` attribute is optional.  If it is not
          defined, the "null" renderer is assumed (no rendering is
          performed and the value is passed back to the upstream
          :app:`Pyramid` machinery unmodified).

        http_cache

          .. versionadded:: 1.1

          When you supply an ``http_cache`` value to a view configuration,
          the ``Expires`` and ``Cache-Control`` headers of a response
          generated by the associated view callable are modified.  The value
          for ``http_cache`` may be one of the following:

          - A nonzero integer.  If it's a nonzero integer, it's treated as a
            number of seconds.  This number of seconds will be used to
            compute the ``Expires`` header and the ``Cache-Control:
            max-age`` parameter of responses to requests which call this view.
            For example: ``http_cache=3600`` instructs the requesting browser
            to 'cache this response for an hour, please'.

          - A ``datetime.timedelta`` instance.  If it's a
            ``datetime.timedelta`` instance, it will be converted into a
            number of seconds, and that number of seconds will be used to
            compute the ``Expires`` header and the ``Cache-Control:
            max-age`` parameter of responses to requests which call this view.
            For example: ``http_cache=datetime.timedelta(days=1)`` instructs
            the requesting browser to 'cache this response for a day, please'.

          - Zero (``0``).  If the value is zero, the ``Cache-Control`` and
            ``Expires`` headers present in all responses from this view will
            be composed such that client browser cache (and any intermediate
            caches) are instructed to never cache the response.

          - A two-tuple.  If it's a two tuple (e.g. ``http_cache=(1,
            {'public':True})``), the first value in the tuple may be a
            nonzero integer or a ``datetime.timedelta`` instance; in either
            case this value will be used as the number of seconds to cache
            the response.  The second value in the tuple must be a
            dictionary.  The values present in the dictionary will be used as
            input to the ``Cache-Control`` response header.  For example:
            ``http_cache=(3600, {'public':True})`` means 'cache for an hour,
            and add ``public`` to the Cache-Control header of the response'.
            All keys and values supported by the
            ``webob.cachecontrol.CacheControl`` interface may be added to the
            dictionary.  Supplying ``{'public':True}`` is equivalent to
            calling ``response.cache_control.public = True``.

          Providing a non-tuple value as ``http_cache`` is equivalent to
          calling ``response.cache_expires(value)`` within your view's body.

          Providing a two-tuple value as ``http_cache`` is equivalent to
          calling ``response.cache_expires(value[0], **value[1])`` within your
          view's body.

          If you wish to avoid influencing, the ``Expires`` header, and
          instead wish to only influence ``Cache-Control`` headers, pass a
          tuple as ``http_cache`` with the first element of ``None``, e.g.:
          ``(None, {'public':True})``.

          If you wish to prevent a view that uses ``http_cache`` in its
          configuration from having its caching response headers changed by
          this machinery, set ``response.cache_control.prevent_auto = True``
          before returning the response from the view.  This effectively
          disables any HTTP caching done by ``http_cache`` for that response.

        wrapper

          The :term:`view name` of a different :term:`view
          configuration` which will receive the response body of this
          view as the ``request.wrapped_body`` attribute of its own
          :term:`request`, and the :term:`response` returned by this
          view as the ``request.wrapped_response`` attribute of its
          own request.  Using a wrapper makes it possible to "chain"
          views together to form a composite response.  The response
          of the outermost wrapper view will be returned to the user.
          The wrapper view will be found as any view is found: see
          :ref:`view_lookup`.  The "best" wrapper view will be found
          based on the lookup ordering: "under the hood" this wrapper
          view is looked up via
          ``pyramid.view.render_view_to_response(context, request,
          'wrapper_viewname')``. The context and request of a wrapper
          view is the same context and request of the inner view.  If
          this attribute is unspecified, no view wrapping is done.

        decorator

          A :term:`dotted Python name` to function (or the function itself,
          or an iterable of the aforementioned) which will be used to
          decorate the registered :term:`view callable`.  The decorator
          function(s) will be called with the view callable as a single
          argument.  The view callable it is passed will accept
          ``(context, request)``.  The decorator(s) must return a
          replacement view callable which also accepts ``(context,
          request)``.

          If decorator is an iterable, the callables will be combined and
          used in the order provided as a decorator.
          For example::

            @view_config(...,
                decorator=(decorator2,
                           decorator1))
            def myview(request):
                ....

          Is similar to doing::

            @view_config(...)
            @decorator2
            @decorator1
            def myview(request):
                ...

          Except with the existing benefits of ``decorator=`` (having a common
          decorator syntax for all view calling conventions and not having to
          think about preserving function attributes such as ``__name__`` and
          ``__module__`` within decorator logic).

          All view callables in the decorator chain must return a response
          object implementing :class:`pyramid.interfaces.IResponse` or raise
          an exception:

          .. code-block:: python

             def log_timer(wrapped):
                 def wrapper(context, request):
                     start = time.time()
                     response = wrapped(context, request)
                     duration = time.time() - start
                     response.headers['X-View-Time'] = '%.3f' % (duration,)
                     log.info('view took %.3f seconds', duration)
                     return response
                 return wrapper

          .. versionchanged:: 1.4a4
             Passing an iterable.

        mapper

          A Python object or :term:`dotted Python name` which refers to a
          :term:`view mapper`, or ``None``.  By default it is ``None``, which
          indicates that the view should use the default view mapper.  This
          plug-point is useful for Pyramid extension developers, but it's not
          very useful for 'civilians' who are just developing stock Pyramid
          applications. Pay no attention to the man behind the curtain.

        accept

          This value represents a match query for one or more mimetypes in the
          ``Accept`` HTTP request header.  If this value is specified, it must
          be in one of the following forms: a mimetype match token in the form
          ``text/plain``, a wildcard mimetype match token in the form
          ``text/*`` or a match-all wildcard mimetype match token in the form
          ``*/*``.  If any of the forms matches the ``Accept`` header of the
          request, or if the ``Accept`` header isn't set at all in the request,
          this will match the current view. If this does not match the
          ``Accept`` header of the request, view matching continues.

        Predicate Arguments

        name

          The :term:`view name`.  Read :ref:`traversal_chapter` to
          understand the concept of a view name.

        context

          An object or a :term:`dotted Python name` referring to an
          interface or class object that the :term:`context` must be
          an instance of, *or* the :term:`interface` that the
          :term:`context` must provide in order for this view to be
          found and called.  This predicate is true when the
          :term:`context` is an instance of the represented class or
          if the :term:`context` provides the represented interface;
          it is otherwise false.  This argument may also be provided
          to ``add_view`` as ``for_`` (an older, still-supported
          spelling).

        route_name

          This value must match the ``name`` of a :term:`route
          configuration` declaration (see :ref:`urldispatch_chapter`)
          that must match before this view will be called.

        request_type

          This value should be an :term:`interface` that the
          :term:`request` must provide in order for this view to be
          found and called.  This value exists only for backwards
          compatibility purposes.

        request_method

          This value can be either a string (such as ``"GET"``, ``"POST"``,
          ``"PUT"``, ``"DELETE"``, ``"HEAD"`` or ``"OPTIONS"``) representing
          an HTTP ``REQUEST_METHOD``, or a tuple containing one or more of
          these strings.  A view declaration with this argument ensures that
          the view will only be called when the ``method`` attribute of the
          request (aka the ``REQUEST_METHOD`` of the WSGI environment) matches
          a supplied value.  Note that use of ``GET`` also implies that the
          view will respond to ``HEAD`` as of Pyramid 1.4.

          .. versionchanged:: 1.2
             The ability to pass a tuple of items as ``request_method``.
             Previous versions allowed only a string.

        request_param

          This value can be any string or any sequence of strings.  A view
          declaration with this argument ensures that the view will only be
          called when the :term:`request` has a key in the ``request.params``
          dictionary (an HTTP ``GET`` or ``POST`` variable) that has a
          name which matches the supplied value (if the value is a string)
          or values (if the value is a tuple).  If any value
          supplied has a ``=`` sign in it,
          e.g. ``request_param="foo=123"``, then the key (``foo``)
          must both exist in the ``request.params`` dictionary, *and*
          the value must match the right hand side of the expression
          (``123``) for the view to "match" the current request.

        match_param

          .. versionadded:: 1.2

          This value can be a string of the format "key=value" or a tuple
          containing one or more of these strings.

          A view declaration with this argument ensures that the view will
          only be called when the :term:`request` has key/value pairs in its
          :term:`matchdict` that equal those supplied in the predicate.
          e.g. ``match_param="action=edit"`` would require the ``action``
          parameter in the :term:`matchdict` match the right hand side of
          the expression (``edit``) for the view to "match" the current
          request.

          If the ``match_param`` is a tuple, every key/value pair must match
          for the predicate to pass.

        containment

          This value should be a Python class or :term:`interface` (or a
          :term:`dotted Python name`) that an object in the
          :term:`lineage` of the context must provide in order for this view
          to be found and called.  The nodes in your object graph must be
          "location-aware" to use this feature.  See
          :ref:`location_aware` for more information about
          location-awareness.

        xhr

          This value should be either ``True`` or ``False``.  If this
          value is specified and is ``True``, the :term:`request`
          must possess an ``HTTP_X_REQUESTED_WITH`` (aka
          ``X-Requested-With``) header that has the value
          ``XMLHttpRequest`` for this view to be found and called.
          This is useful for detecting AJAX requests issued from
          jQuery, Prototype and other Javascript libraries.

        header

          This value represents an HTTP header name or a header
          name/value pair.  If the value contains a ``:`` (colon), it
          will be considered a name/value pair
          (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).  The
          value portion should be a regular expression.  If the value
          does not contain a colon, the entire value will be
          considered to be the header name
          (e.g. ``If-Modified-Since``).  If the value evaluates to a
          header name only without a value, the header specified by
          the name must be present in the request for this predicate
          to be true.  If the value evaluates to a header name/value
          pair, the header specified by the name must be present in
          the request *and* the regular expression specified as the
          value must match the header value.  Whether or not the value
          represents a header name or a header name/value pair, the
          case of the header name is not significant.

        path_info

          This value represents a regular expression pattern that will
          be tested against the ``PATH_INFO`` WSGI environment
          variable.  If the regex matches, this predicate will be
          ``True``.

        check_csrf

          If specified, this value should be one of ``None``, ``True``,
          ``False``, or a string representing the 'check name'.  If the value
          is ``True`` or a string, CSRF checking will be performed.  If the
          value is ``False`` or ``None``, CSRF checking will not be performed.

          If the value provided is a string, that string will be used as the
          'check name'.  If the value provided is ``True``, ``csrf_token`` will
          be used as the check name.

          If CSRF checking is performed, the checked value will be the value
          of ``request.params[check_name]``.  This value will be compared
          against the value of ``request.session.get_csrf_token()``, and the
          check will pass if these two values are the same.  If the check
          passes, the associated view will be permitted to execute.  If the
          check fails, the associated view will not be permitted to execute.

          Note that using this feature requires a :term:`session factory` to
          have been configured.

          .. versionadded:: 1.4a2

        physical_path

          If specified, this value should be a string or a tuple representing
          the :term:`physical path` of the context found via traversal for this
          predicate to match as true.  For example: ``physical_path='/'`` or
          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.
          This is not a path prefix match or a regex, it's a whole-path match.
          It's useful when you want to always potentially show a view when some
          object is traversed to, but you can't be sure about what kind of
          object it will be, so you can't use the ``context`` predicate.  The
          individual path elements inbetween slash characters or in tuple
          elements should be the Unicode representation of the name of the
          resource and should not be encoded in any way.

          .. versionadded:: 1.4a3

        effective_principals

          If specified, this value should be a :term:`principal` identifier or
          a sequence of principal identifiers.  If the
          :attr:`pyramid.request.Request.effective_principals` property
          indicates that every principal named in the argument list is present
          in the current request, this predicate will return True; otherwise it
          will return False.  For example:
          ``effective_principals=pyramid.security.Authenticated`` or
          ``effective_principals=('fred', 'group:admins')``.

          .. versionadded:: 1.4a4

        custom_predicates

            .. deprecated:: 1.5
                This value should be a sequence of references to custom
                predicate callables.  Use custom predicates when no set of
                predefined predicates do what you need.  Custom predicates
                can be combined with predefined predicates as necessary.
                Each custom predicate callable should accept two arguments:
                ``context`` and ``request`` and should return either
                ``True`` or ``False`` after doing arbitrary evaluation of
                the context and/or the request.  The ``predicates`` argument
                to this method and the ability to register third-party view
                predicates via
                :meth:`pyramid.config.Configurator.add_view_predicate`
                obsoletes this argument, but it is kept around for backwards
                compatibility.

        view_options:

          Pass a key/value pair here to use a third-party predicate or set a
          value for a view deriver. See
          :meth:`pyramid.config.Configurator.add_view_predicate` and
          :meth:`pyramid.config.Configurator.add_view_deriver`. See
          :ref:`view_and_route_predicates` for more information about
          third-party predicates and :ref:`view_derivers` for information
          about view derivers.

          .. versionadded: 1.4a1

          .. versionchanged: 1.7

             Support setting view deriver options. Previously, only custom
             view predicate values could be supplied.

        """
        if custom_predicates:
            warnings.warn(
                ('The "custom_predicates" argument to Configurator.add_view '
                 'is deprecated as of Pyramid 1.5.  Use '
                 '"config.add_view_predicate" and use the registered '
                 'view predicate as a predicate argument to add_view instead. '
                 'See "Adding A Third Party View, Route, or Subscriber '
                 'Predicate" in the "Hooks" chapter of the documentation '
                 'for more information.'),
                DeprecationWarning,
                stacklevel=4
                )

        view = self.maybe_dotted(view)
        context = self.maybe_dotted(context)
        for_ = self.maybe_dotted(for_)
        containment = self.maybe_dotted(containment)
        mapper = self.maybe_dotted(mapper)

        def combine(*decorators):
            def decorated(view_callable):
                # reversed() allows a more natural ordering in the api
                for decorator in reversed(decorators):
                    view_callable = decorator(view_callable)
                return view_callable
            return decorated

        if is_nonstr_iter(decorator):
            decorator = combine(*map(self.maybe_dotted, decorator))
        else:
            decorator = self.maybe_dotted(decorator)

        if not view:
            if renderer:
                def view(context, request):
                    return {}
            else:
                raise ConfigurationError('"view" was not specified and '
                                         'no "renderer" specified')

        if request_type is not None:
            request_type = self.maybe_dotted(request_type)
            if not IInterface.providedBy(request_type):
                raise ConfigurationError(
                    'request_type must be an interface, not %s' % request_type)

        if context is None:
            context = for_

        r_context = context
        if r_context is None:
            r_context = Interface
        if not IInterface.providedBy(r_context):
            r_context = implementedBy(r_context)

        if isinstance(renderer, string_types):
            renderer = renderers.RendererHelper(
                name=renderer, package=self.package,
                registry=self.registry)

        if accept is not None:
            accept = accept.lower()

        introspectables = []
        ovals = view_options.copy()
        ovals.update(dict(
            xhr=xhr,
            request_method=request_method,
            path_info=path_info,
            request_param=request_param,
            header=header,
            accept=accept,
            containment=containment,
            request_type=request_type,
            match_param=match_param,
            check_csrf=check_csrf,
            custom=predvalseq(custom_predicates),
        ))

        def discrim_func():
            # We need to defer the discriminator until we know what the phash
            # is.  It can't be computed any sooner because thirdparty
            # predicates/view derivers may not yet exist when add_view is
            # called.
            valid_predicates = predlist.names()
            pvals = {}
            dvals = {}

            for (k, v) in ovals.items():
                if k in valid_predicates:
                    pvals[k] = v
                else:
                    dvals[k] = v

            self._check_view_options(**dvals)

            order, preds, phash = predlist.make(self, **pvals)

            view_intr.update({
                'phash': phash,
                'order': order,
                'predicates': preds,
                })
            return ('view', context, name, route_name, phash)

        discriminator = Deferred(discrim_func)

        if inspect.isclass(view) and attr:
            view_desc = 'method %r of %s' % (
                attr, self.object_description(view))
        else:
            view_desc = self.object_description(view)

        tmpl_intr = None

        view_intr = self.introspectable('views',
                                        discriminator,
                                        view_desc,
                                        'view')
        view_intr.update(dict(
            name=name,
            context=context,
            containment=containment,
            request_param=request_param,
            request_methods=request_method,
            route_name=route_name,
            attr=attr,
            xhr=xhr,
            accept=accept,
            header=header,
            path_info=path_info,
            match_param=match_param,
            check_csrf=check_csrf,
            callable=view,
            mapper=mapper,
            decorator=decorator,
        ))
        view_intr.update(view_options)
        introspectables.append(view_intr)
        predlist = self.get_predlist('view')

        def register(permission=permission, renderer=renderer):
            request_iface = IRequest
            if route_name is not None:
                request_iface = self.registry.queryUtility(IRouteRequest,
                                                           name=route_name)
                if request_iface is None:
                    # route configuration should have already happened in
                    # phase 2
                    raise ConfigurationError(
                        'No route named %s found for view registration' %
                        route_name)

            if renderer is None:
                # use default renderer if one exists (reg'd in phase 1)
                if self.registry.queryUtility(IRendererFactory) is not None:
                    renderer = renderers.RendererHelper(
                        name=None,
                        package=self.package,
                        registry=self.registry
                        )

            if permission is None:
                # intent: will be None if no default permission is registered
                # (reg'd in phase 1)
                permission = self.registry.queryUtility(IDefaultPermission)

            # added by discrim_func above during conflict resolving
            preds = view_intr['predicates']
            order = view_intr['order']
            phash = view_intr['phash']

            # __no_permission_required__ handled by _secure_view
            derived_view = self._derive_view(
                view,
                permission=permission,
                predicates=preds,
                attr=attr,
                context=context,
                renderer=renderer,
                wrapper_viewname=wrapper,
                viewname=name,
                accept=accept,
                order=order,
                phash=phash,
                decorator=decorator,
                mapper=mapper,
                http_cache=http_cache,
                extra_options=ovals,
            )
            derived_view.__discriminator__ = lambda *arg: discriminator
            # __discriminator__ is used by superdynamic systems
            # that require it for introspection after manual view lookup;
            # see also MultiView.__discriminator__
            view_intr['derived_callable'] = derived_view

            registered = self.registry.adapters.registered

            # A multiviews is a set of views which are registered for
            # exactly the same context type/request type/name triad.  Each
            # consituent view in a multiview differs only by the
            # predicates which it possesses.

            # To find a previously registered view for a context
            # type/request type/name triad, we need to use the
            # ``registered`` method of the adapter registry rather than
            # ``lookup``.  ``registered`` ignores interface inheritance
            # for the required and provided arguments, returning only a
            # view registered previously with the *exact* triad we pass
            # in.

            # We need to do this three times, because we use three
            # different interfaces as the ``provided`` interface while
            # doing registrations, and ``registered`` performs exact
            # matches on all the arguments it receives.

            old_view = None

            for view_type in (IView, ISecuredView, IMultiView):
                old_view = registered((IViewClassifier, request_iface,
                                       r_context), view_type, name)
                if old_view is not None:
                    break

            isexc = isexception(context)

            def regclosure():
                if hasattr(derived_view, '__call_permissive__'):
                    view_iface = ISecuredView
                else:
                    view_iface = IView
                self.registry.registerAdapter(
                    derived_view,
                    (IViewClassifier, request_iface, context), view_iface, name
                    )
                if isexc:
                    self.registry.registerAdapter(
                        derived_view,
                        (IExceptionViewClassifier, request_iface, context),
                        view_iface, name)

            is_multiview = IMultiView.providedBy(old_view)
            old_phash = getattr(old_view, '__phash__', DEFAULT_PHASH)

            if old_view is None:
                # - No component was yet registered for any of our I*View
                #   interfaces exactly; this is the first view for this
                #   triad.
                regclosure()

            elif (not is_multiview) and (old_phash == phash):
                # - A single view component was previously registered with
                #   the same predicate hash as this view; this registration
                #   is therefore an override.
                regclosure()

            else:
                # - A view or multiview was already registered for this
                #   triad, and the new view is not an override.

                # XXX we could try to be more efficient here and register
                # a non-secured view for a multiview if none of the
                # multiview's consituent views have a permission
                # associated with them, but this code is getting pretty
                # rough already
                if is_multiview:
                    multiview = old_view
                else:
                    multiview = MultiView(name)
                    old_accept = getattr(old_view, '__accept__', None)
                    old_order = getattr(old_view, '__order__', MAX_ORDER)
                    multiview.add(old_view, old_order, old_accept, old_phash)
                multiview.add(derived_view, order, accept, phash)
                for view_type in (IView, ISecuredView):
                    # unregister any existing views
                    self.registry.adapters.unregister(
                        (IViewClassifier, request_iface, r_context),
                        view_type, name=name)
                    if isexc:
                        self.registry.adapters.unregister(
                            (IExceptionViewClassifier, request_iface,
                             r_context), view_type, name=name)
                self.registry.registerAdapter(
                    multiview,
                    (IViewClassifier, request_iface, context),
                    IMultiView, name=name)
                if isexc:
                    self.registry.registerAdapter(
                        multiview,
                        (IExceptionViewClassifier, request_iface, context),
                        IMultiView, name=name)

            self.registry._clear_view_lookup_cache()
            renderer_type = getattr(renderer, 'type', None) # gard against None
            intrspc = self.introspector
            if (
                renderer_type is not None and
                tmpl_intr is not None and
                intrspc is not None and
                intrspc.get('renderer factories', renderer_type) is not None
                ):
                # allow failure of registered template factories to be deferred
                # until view execution, like other bad renderer factories; if
                # we tried to relate this to an existing renderer factory
                # without checking if it the factory actually existed, we'd end
                # up with a KeyError at startup time, which is inconsistent
                # with how other bad renderer registrations behave (they throw
                # a ValueError at view execution time)
                tmpl_intr.relate('renderer factories', renderer.type)

        if mapper:
            mapper_intr = self.introspectable(
                'view mappers',
                discriminator,
                'view mapper for %s' % view_desc,
                'view mapper'
                )
            mapper_intr['mapper'] = mapper
            mapper_intr.relate('views', discriminator)
            introspectables.append(mapper_intr)
        if route_name:
            view_intr.relate('routes', route_name) # see add_route
        if renderer is not None and renderer.name and '.' in renderer.name:
            # the renderer is a template
            tmpl_intr = self.introspectable(
                'templates',
                discriminator,
                renderer.name,
                'template'
                )
            tmpl_intr.relate('views', discriminator)
            tmpl_intr['name'] = renderer.name
            tmpl_intr['type'] = renderer.type
            tmpl_intr['renderer'] = renderer
            introspectables.append(tmpl_intr)
        if permission is not None:
            # if a permission exists, register a permission introspectable
            perm_intr = self.introspectable(
                'permissions',
                permission,
                permission,
                'permission'
                )
            perm_intr['value'] = permission
            perm_intr.relate('views', discriminator)
            introspectables.append(perm_intr)
        self.action(discriminator, register, introspectables=introspectables)

    def _check_view_options(self, **kw):
        # we only need to validate deriver options because the predicates
        # were checked by the predlist
        derivers = self.registry.getUtility(IViewDerivers)
        for deriver in derivers.values():
            for opt in getattr(deriver, 'options', []):
                kw.pop(opt, None)
        if kw:
            raise ConfigurationError('Unknown view options: %s' % (kw,))

    def _apply_view_derivers(self, info):
        d = pyramid.viewderivers

        # These derivers are not really derivers and so have fixed order
        outer_derivers = [('attr_wrapped_view', d.attr_wrapped_view),
                          ('predicated_view', d.predicated_view)]

        view = info.original_view
        derivers = self.registry.getUtility(IViewDerivers)
        for name, deriver in reversed(outer_derivers + derivers.sorted()):
            view = wraps_view(deriver)(view, info)
        return view

    @action_method
    def add_view_predicate(self, name, factory, weighs_more_than=None,
                           weighs_less_than=None):
        """
        .. versionadded:: 1.4

        Adds a view predicate factory.  The associated view predicate can
        later be named as a keyword argument to
        :meth:`pyramid.config.Configurator.add_view` in the
        ``predicates`` anonyous keyword argument dictionary.

        ``name`` should be the name of the predicate.  It must be a valid
        Python identifier (it will be used as a keyword argument to
        ``add_view`` by others).

        ``factory`` should be a :term:`predicate factory` or :term:`dotted
        Python name` which refers to a predicate factory.

        See :ref:`view_and_route_predicates` for more information.
        """
        self._add_predicate(
            'view',
            name,
            factory,
            weighs_more_than=weighs_more_than,
            weighs_less_than=weighs_less_than
            )

    def add_default_view_predicates(self):
        p = pyramid.config.predicates
        for (name, factory) in (
            ('xhr', p.XHRPredicate),
            ('request_method', p.RequestMethodPredicate),
            ('path_info', p.PathInfoPredicate),
            ('request_param', p.RequestParamPredicate),
            ('header', p.HeaderPredicate),
            ('accept', p.AcceptPredicate),
            ('containment', p.ContainmentPredicate),
            ('request_type', p.RequestTypePredicate),
            ('match_param', p.MatchParamPredicate),
            ('check_csrf', p.CheckCSRFTokenPredicate),
            ('physical_path', p.PhysicalPathPredicate),
            ('effective_principals', p.EffectivePrincipalsPredicate),
            ('custom', p.CustomPredicate),
            ):
            self.add_view_predicate(name, factory)

    @action_method
    def add_view_deriver(self, deriver, name=None, under=None, over=None):
        """
        .. versionadded:: 1.7

        Add a :term:`view deriver` to the view pipeline. View derivers are
        a feature used by extension authors to wrap views in custom code
        controllable by view-specific options.

        ``deriver`` should be a callable conforming to the
        :class:`pyramid.interfaces.IViewDeriver` interface.

        ``name`` should be the name of the view deriver.  There are no
        restrictions on the name of a view deriver. If left unspecified, the
        name will be constructed from the name of the ``deriver``.

        The ``under`` and ``over`` options can be used to control the ordering
        of view derivers by providing hints about where in the view pipeline
        the deriver is used. Each option may be a string or a list of strings.
        At least one view deriver in each, the over and under directions, must
        exist to fully satisfy the constraints.

        ``under`` means closer to the user-defined :term:`view callable`,
        and ``over`` means closer to view pipeline ingress.

        Specifying neither ``under`` nor ``over`` is equivalent to specifying
        ``over='rendered_view'`` and ``under='decorated_view'``, placing the
        deriver somewhere between the ``decorated_view`` and ``rendered_view``
        derivers.

        See :ref:`view_derivers` for more information.

        """
        deriver = self.maybe_dotted(deriver)

        if name is None:
            name = deriver.__name__

        if name in (INGRESS,):
            raise ConfigurationError('%s is a reserved view deriver name'
                                     % name)

        if under is None and over is None:
            under = 'decorated_view'
            over = 'rendered_view'

        if over is None and name != MAPPED_VIEW:
            raise ConfigurationError('must specify an "over" constraint for '
                                     'the %s view deriver' % name)
        elif over is not None:
            over = as_sorted_tuple(over)

        if under is None:
            raise ConfigurationError('must specify an "under" constraint for '
                                     'the %s view deriver' % name)
        else:
            under = as_sorted_tuple(under)

        if over is not None and INGRESS in over:
            raise ConfigurationError('%s cannot be over view deriver INGRESS'
                                     % name)

        if MAPPED_VIEW in under:
            raise ConfigurationError('%s cannot be under view deriver '
                                     'MAPPED_VIEW' % name)

        discriminator = ('view deriver', name)
        intr = self.introspectable(
            'view derivers',
            name,
            name,
            'view deriver')
        intr['name'] = name
        intr['deriver'] = deriver
        intr['under'] = under
        intr['over'] = over
        def register():
            derivers = self.registry.queryUtility(IViewDerivers)
            if derivers is None:
                derivers = TopologicalSorter(
                    default_before=None,
                    default_after=INGRESS,
                    first=INGRESS,
                    last=MAPPED_VIEW,
                )
                self.registry.registerUtility(derivers, IViewDerivers)
            derivers.add(name, deriver, before=over, after=under)
        self.action(discriminator, register, introspectables=(intr,),
                    order=PHASE1_CONFIG) # must be registered before add_view

    def add_default_view_derivers(self):
        d = pyramid.viewderivers
        derivers = [
            ('secured_view', d.secured_view),
            ('owrapped_view', d.owrapped_view),
            ('http_cached_view', d.http_cached_view),
            ('decorated_view', d.decorated_view),
            ('rendered_view', d.rendered_view),
        ]
        last = INGRESS
        for name, deriver in derivers:
            self.add_view_deriver(
                deriver,
                name=name,
                under=last,
                over=MAPPED_VIEW,
            )
            last = name

        self.add_view_deriver(d.mapped_view, name=MAPPED_VIEW, under=last)

    def derive_view(self, view, attr=None, renderer=None):
        """
        Create a :term:`view callable` using the function, instance,
        or class (or :term:`dotted Python name` referring to the same)
        provided as ``view`` object.

        .. warning::

           This method is typically only used by :app:`Pyramid` framework
           extension authors, not by :app:`Pyramid` application developers.

        This is API is useful to framework extenders who create
        pluggable systems which need to register 'proxy' view
        callables for functions, instances, or classes which meet the
        requirements of being a :app:`Pyramid` view callable.  For
        example, a ``some_other_framework`` function in another
        framework may want to allow a user to supply a view callable,
        but he may want to wrap the view callable in his own before
        registering the wrapper as a :app:`Pyramid` view callable.
        Because a :app:`Pyramid` view callable can be any of a
        number of valid objects, the framework extender will not know
        how to call the user-supplied object.  Running it through
        ``derive_view`` normalizes it to a callable which accepts two
        arguments: ``context`` and ``request``.

        For example:

        .. code-block:: python

           def some_other_framework(user_supplied_view):
               config = Configurator(reg)
               proxy_view = config.derive_view(user_supplied_view)
               def my_wrapper(context, request):
                   do_something_that_mutates(request)
                   return proxy_view(context, request)
               config.add_view(my_wrapper)

        The ``view`` object provided should be one of the following:

        - A function or another non-class callable object that accepts
          a :term:`request` as a single positional argument and which
          returns a :term:`response` object.

        - A function or other non-class callable object that accepts
          two positional arguments, ``context, request`` and which
          returns a :term:`response` object.

        - A class which accepts a single positional argument in its
          constructor named ``request``, and which has a ``__call__``
          method that accepts no arguments that returns a
          :term:`response` object.

        - A class which accepts two positional arguments named
          ``context, request``, and which has a ``__call__`` method
          that accepts no arguments that returns a :term:`response`
          object.

        - A :term:`dotted Python name` which refers to any of the
          kinds of objects above.

        This API returns a callable which accepts the arguments
        ``context, request`` and which returns the result of calling
        the provided ``view`` object.

        The ``attr`` keyword argument is most useful when the view
        object is a class.  It names the method that should be used as
        the callable.  If ``attr`` is not provided, the attribute
        effectively defaults to ``__call__``.  See
        :ref:`class_as_view` for more information.

        The ``renderer`` keyword argument should be a renderer
        name. If supplied, it will cause the returned callable to use
        a :term:`renderer` to convert the user-supplied view result to
        a :term:`response` object.  If a ``renderer`` argument is not
        supplied, the user-supplied view must itself return a
        :term:`response` object.  """
        return self._derive_view(view, attr=attr, renderer=renderer)

    # b/w compat
    def _derive_view(self, view, permission=None, predicates=(),
                     attr=None, renderer=None, wrapper_viewname=None,
                     viewname=None, accept=None, order=MAX_ORDER,
                     phash=DEFAULT_PHASH, decorator=None,
                     mapper=None, http_cache=None, context=None,
                     extra_options=None):
        view = self.maybe_dotted(view)
        mapper = self.maybe_dotted(mapper)
        if isinstance(renderer, string_types):
            renderer = renderers.RendererHelper(
                name=renderer, package=self.package,
                registry=self.registry)
        if renderer is None:
            # use default renderer if one exists
            if self.registry.queryUtility(IRendererFactory) is not None:
                renderer = renderers.RendererHelper(
                    name=None,
                    package=self.package,
                    registry=self.registry)

        options = dict(
            view=view,
            context=context,
            permission=permission,
            attr=attr,
            renderer=renderer,
            wrapper=wrapper_viewname,
            name=viewname,
            accept=accept,
            mapper=mapper,
            decorator=decorator,
            http_cache=http_cache,
        )
        if extra_options:
            options.update(extra_options)

        info = ViewDeriverInfo(
            view=view,
            registry=self.registry,
            package=self.package,
            predicates=predicates,
            options=options,
        )

        # order and phash are only necessary for the predicated view and
        # are not really view deriver options
        info.order = order
        info.phash = phash

        return self._apply_view_derivers(info)

    @viewdefaults
    @action_method
    def add_forbidden_view(
        self,
        view=None,
        attr=None,
        renderer=None,
        wrapper=None,
        route_name=None,
        request_type=None,
        request_method=None,
        request_param=None,
        containment=None,
        xhr=None,
        accept=None,
        header=None,
        path_info=None,
        custom_predicates=(),
        decorator=None,
        mapper=None,
        match_param=None,
        **view_options
        ):
        """ Add a forbidden view to the current configuration state.  The
        view will be called when Pyramid or application code raises a
        :exc:`pyramid.httpexceptions.HTTPForbidden` exception and the set of
        circumstances implied by the predicates provided are matched.  The
        simplest example is:

          .. code-block:: python

            def forbidden(request):
                return Response('Forbidden', status='403 Forbidden')

            config.add_forbidden_view(forbidden)

        If ``view`` argument is not provided, the view callable defaults to
        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.

        All arguments have the same meaning as
        :meth:`pyramid.config.Configurator.add_view` and each predicate
        argument restricts the set of circumstances under which this forbidden
        view will be invoked.  Unlike
        :meth:`pyramid.config.Configurator.add_view`, this method will raise
        an exception if passed ``name``, ``permission``, ``context``,
        ``for_``, or ``http_cache`` keyword arguments.  These argument values
        make no sense in the context of a forbidden view.

        .. versionadded:: 1.3
        """
        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):
            if arg in view_options:
                raise ConfigurationError(
                    '%s may not be used as an argument to add_forbidden_view'
                    % arg
                    )

        if view is None:
            view = default_exceptionresponse_view

        settings = dict(
            view=view,
            context=HTTPForbidden,
            wrapper=wrapper,
            request_type=request_type,
            request_method=request_method,
            request_param=request_param,
            containment=containment,
            xhr=xhr,
            accept=accept,
            header=header,
            path_info=path_info,
            custom_predicates=custom_predicates,
            decorator=decorator,
            mapper=mapper,
            match_param=match_param,
            route_name=route_name,
            permission=NO_PERMISSION_REQUIRED,
            attr=attr,
            renderer=renderer,
            )
        settings.update(view_options)
        return self.add_view(**settings)

    set_forbidden_view = add_forbidden_view # deprecated sorta-bw-compat alias

    @viewdefaults
    @action_method
    def add_notfound_view(
        self,
        view=None,
        attr=None,
        renderer=None,
        wrapper=None,
        route_name=None,
        request_type=None,
        request_method=None,
        request_param=None,
        containment=None,
        xhr=None,
        accept=None,
        header=None,
        path_info=None,
        custom_predicates=(),
        decorator=None,
        mapper=None,
        match_param=None,
        append_slash=False,
        **view_options
        ):
        """ Add a default Not Found View to the current configuration state.
        The view will be called when Pyramid or application code raises an
        :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a
        view cannot be found for the request).  The simplest example is:

          .. code-block:: python

            def notfound(request):
                return Response('Not Found', status='404 Not Found')

            config.add_notfound_view(notfound)

        If ``view`` argument is not provided, the view callable defaults to
        :func:`~pyramid.httpexceptions.default_exceptionresponse_view`.

        All arguments except ``append_slash`` have the same meaning as
        :meth:`pyramid.config.Configurator.add_view` and each predicate
        argument restricts the set of circumstances under which this notfound
        view will be invoked.  Unlike
        :meth:`pyramid.config.Configurator.add_view`, this method will raise
        an exception if passed ``name``, ``permission``, ``context``,
        ``for_``, or ``http_cache`` keyword arguments.  These argument values
        make no sense in the context of a Not Found View.

        If ``append_slash`` is ``True``, when this Not Found View is invoked,
        and the current path info does not end in a slash, the notfound logic
        will attempt to find a :term:`route` that matches the request's path
        info suffixed with a slash.  If such a route exists, Pyramid will
        issue a redirect to the URL implied by the route; if it does not,
        Pyramid will return the result of the view callable provided as
        ``view``, as normal.

        If the argument provided as ``append_slash`` is not a boolean but
        instead implements :class:`~pyramid.interfaces.IResponse`, the
        append_slash logic will behave as if ``append_slash=True`` was passed,
        but the provided class will be used as the response class instead of
        the default :class:`~pyramid.httpexceptions.HTTPFound` response class
        when a redirect is performed.  For example:

          .. code-block:: python

            from pyramid.httpexceptions import HTTPMovedPermanently
            config.add_notfound_view(append_slash=HTTPMovedPermanently)

        The above means that a redirect to a slash-appended route will be
        attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound`
        being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will
        be used` for the redirect response if a slash-appended route is found.

        .. versionchanged:: 1.6
        .. versionadded:: 1.3
        """
        for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):
            if arg in view_options:
                raise ConfigurationError(
                    '%s may not be used as an argument to add_notfound_view'
                    % arg
                    )

        if view is None:
            view = default_exceptionresponse_view

        settings = dict(
            view=view,
            context=HTTPNotFound,
            wrapper=wrapper,
            request_type=request_type,
            request_method=request_method,
            request_param=request_param,
            containment=containment,
            xhr=xhr,
            accept=accept,
            header=header,
            path_info=path_info,
            custom_predicates=custom_predicates,
            decorator=decorator,
            mapper=mapper,
            match_param=match_param,
            route_name=route_name,
            permission=NO_PERMISSION_REQUIRED,
            )
        settings.update(view_options)
        if append_slash:
            view = self._derive_view(view, attr=attr, renderer=renderer)
            if IResponse.implementedBy(append_slash):
                view = AppendSlashNotFoundViewFactory(
                    view, redirect_class=append_slash,
                )
            else:
                view = AppendSlashNotFoundViewFactory(view)
            settings['view'] = view
        else:
            settings['attr'] = attr
            settings['renderer'] = renderer
        return self.add_view(**settings)

    set_notfound_view = add_notfound_view # deprecated sorta-bw-compat alias

    @action_method
    def set_view_mapper(self, mapper):
        """
        Setting a :term:`view mapper` makes it possible to make use of
        :term:`view callable` objects which implement different call
        signatures than the ones supported by :app:`Pyramid` as described in
        its narrative documentation.

        The ``mapper`` argument should be an object implementing
        :class:`pyramid.interfaces.IViewMapperFactory` or a :term:`dotted
        Python name` to such an object.  The provided ``mapper`` will become
        the default view mapper to be used by all subsequent :term:`view
        configuration` registrations.

        .. seealso::

            See also :ref:`using_a_view_mapper`.

        .. note::

           Using the ``default_view_mapper`` argument to the
           :class:`pyramid.config.Configurator` constructor
           can be used to achieve the same purpose.
        """
        mapper = self.maybe_dotted(mapper)
        def register():
            self.registry.registerUtility(mapper, IViewMapperFactory)
        # IViewMapperFactory is looked up as the result of view config
        # in phase 3
        intr = self.introspectable('view mappers',
                                   IViewMapperFactory,
                                   self.object_description(mapper),
                                   'default view mapper')
        intr['mapper'] = mapper
        self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,
                    introspectables=(intr,))

    @action_method
    def add_static_view(self, name, path, **kw):
        """ Add a view used to render static assets such as images
        and CSS files.

        The ``name`` argument is a string representing an
        application-relative local URL prefix.  It may alternately be a full
        URL.

        The ``path`` argument is the path on disk where the static files
        reside.  This can be an absolute path, a package-relative path, or a
        :term:`asset specification`.

        The ``cache_max_age`` keyword argument is input to set the
        ``Expires`` and ``Cache-Control`` headers for static assets served.
        Note that this argument has no effect when the ``name`` is a *url
        prefix*.  By default, this argument is ``None``, meaning that no
        particular Expires or Cache-Control headers are set in the response.

        The ``permission`` keyword argument is used to specify the
        :term:`permission` required by a user to execute the static view.  By
        default, it is the string
        :data:`pyramid.security.NO_PERMISSION_REQUIRED`, a special sentinel
        which indicates that, even if a :term:`default permission` exists for
        the current application, the static view should be renderered to
        completely anonymous users.  This default value is permissive
        because, in most web apps, static assets seldom need protection from
        viewing.  If ``permission`` is specified, the security checking will
        be performed against the default root factory ACL.

        Any other keyword arguments sent to ``add_static_view`` are passed on
        to :meth:`pyramid.config.Configurator.add_route` (e.g. ``factory``,
        perhaps to define a custom factory with a custom ACL for this static
        view).

        *Usage*

        The ``add_static_view`` function is typically used in conjunction
        with the :meth:`pyramid.request.Request.static_url` method.
        ``add_static_view`` adds a view which renders a static asset when
        some URL is visited; :meth:`pyramid.request.Request.static_url`
        generates a URL to that asset.

        The ``name`` argument to ``add_static_view`` is usually a simple URL
        prefix (e.g. ``'images'``).  When this is the case, the
        :meth:`pyramid.request.Request.static_url` API will generate a URL
        which points to a Pyramid view, which will serve up a set of assets
        that live in the package itself. For example:

        .. code-block:: python

           add_static_view('images', 'mypackage:images/')

        Code that registers such a view can generate URLs to the view via
        :meth:`pyramid.request.Request.static_url`:

        .. code-block:: python

           request.static_url('mypackage:images/logo.png')

        When ``add_static_view`` is called with a ``name`` argument that
        represents a URL prefix, as it is above, subsequent calls to
        :meth:`pyramid.request.Request.static_url` with paths that start with
        the ``path`` argument passed to ``add_static_view`` will generate a
        URL something like ``http://<Pyramid app URL>/images/logo.png``,
        which will cause the ``logo.png`` file in the ``images`` subdirectory
        of the ``mypackage`` package to be served.

        ``add_static_view`` can alternately be used with a ``name`` argument
        which is a *URL*, causing static assets to be served from an external
        webserver.  This happens when the ``name`` argument is a fully
        qualified URL (e.g. starts with ``http://`` or similar).  In this
        mode, the ``name`` is used as the prefix of the full URL when
        generating a URL using :meth:`pyramid.request.Request.static_url`.
        Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)
        is used as the ``name`` argument, the generated URL will use the
        protocol of the request (http or https, respectively).

        For example, if ``add_static_view`` is called like so:

        .. code-block:: python

           add_static_view('http://example.com/images', 'mypackage:images/')

        Subsequently, the URLs generated by
        :meth:`pyramid.request.Request.static_url` for that static view will
        be prefixed with ``http://example.com/images`` (the external webserver
        listening on ``example.com`` must be itself configured to respond
        properly to such a request.):

        .. code-block:: python

           static_url('mypackage:images/logo.png', request)

        See :ref:`static_assets_section` for more information.
        """
        spec = self._make_spec(path)
        info = self._get_static_info()
        info.add(self, name, spec, **kw)

    def add_cache_buster(self, path, cachebust, explicit=False):
        """
        Add a cache buster to a set of files on disk.

        The ``path`` should be the path on disk where the static files
        reside.  This can be an absolute path, a package-relative path, or a
        :term:`asset specification`.

        The ``cachebust`` argument may be set to cause
        :meth:`~pyramid.request.Request.static_url` to use cache busting when
        generating URLs. See :ref:`cache_busting` for general information
        about cache busting. The value of the ``cachebust`` argument must
        be an object which implements
        :class:`~pyramid.interfaces.ICacheBuster`.

        If ``explicit`` is set to ``True`` then the ``path`` for the cache
        buster will be matched based on the ``rawspec`` instead of the
        ``pathspec`` as defined in the
        :class:`~pyramid.interfaces.ICacheBuster` interface.
        Default: ``False``.

        """
        spec = self._make_spec(path)
        info = self._get_static_info()
        info.add_cache_buster(self, spec, cachebust, explicit=explicit)

    def _get_static_info(self):
        info = self.registry.queryUtility(IStaticURLInfo)
        if info is None:
            info = StaticURLInfo()
            self.registry.registerUtility(info, IStaticURLInfo)
        return info

def isexception(o):
    if IInterface.providedBy(o):
        if IException.isEqualOrExtendedBy(o):
            return True
    return (
        isinstance(o, Exception) or
        (inspect.isclass(o) and (issubclass(o, Exception)))
        )

@implementer(IViewDeriverInfo)
class ViewDeriverInfo(object):
    def __init__(self, view, registry, package, predicates, options):
        self.original_view = view
        self.registry = registry
        self.package = package
        self.predicates = predicates or []
        self.options = options or {}

    @reify
    def settings(self):
        return self.registry.settings

@implementer(IStaticURLInfo)
class StaticURLInfo(object):
    def __init__(self):
        self.registrations = []
        self.cache_busters = []

    def generate(self, path, request, **kw):
        for (url, spec, route_name) in self.registrations:
            if path.startswith(spec):
                subpath = path[len(spec):]
                if WIN: # pragma: no cover
                    subpath = subpath.replace('\\', '/') # windows
                if self.cache_busters:
                    subpath, kw = self._bust_asset_path(
                        request, spec, subpath, kw)
                if url is None:
                    kw['subpath'] = subpath
                    return request.route_url(route_name, **kw)
                else:
                    app_url, scheme, host, port, qs, anchor = \
                        parse_url_overrides(kw)
                    parsed = url_parse(url)
                    if not parsed.scheme:
                        url = urlparse.urlunparse(parsed._replace(
                            scheme=request.environ['wsgi.url_scheme']))
                    subpath = url_quote(subpath)
                    result = urljoin(url, subpath)
                    return result + qs + anchor

        raise ValueError('No static URL definition matching %s' % path)

    def add(self, config, name, spec, **extra):
        # This feature only allows for the serving of a directory and
        # the files contained within, not of a single asset;
        # appending a slash here if the spec doesn't have one is
        # required for proper prefix matching done in ``generate``
        # (``subpath = path[len(spec):]``).
        if os.path.isabs(spec): # FBO windows
            sep = os.sep
        else:
            sep = '/'
        if not spec.endswith(sep) and not spec.endswith(':'):
            spec = spec + sep

        # we also make sure the name ends with a slash, purely as a
        # convenience: a name that is a url is required to end in a
        # slash, so that ``urljoin(name, subpath))`` will work above
        # when the name is a URL, and it doesn't hurt things for it to
        # have a name that ends in a slash if it's used as a route
        # name instead of a URL.
        if not name.endswith('/'):
            # make sure it ends with a slash
            name = name + '/'

        if url_parse(name).netloc:
            # it's a URL
            # url, spec, route_name
            url = name
            route_name = None
        else:
            # it's a view name
            url = None
            cache_max_age = extra.pop('cache_max_age', None)

            # create a view
            view = static_view(spec, cache_max_age=cache_max_age,
                               use_subpath=True)

            # Mutate extra to allow factory, etc to be passed through here.
            # Treat permission specially because we'd like to default to
            # permissiveness (see docs of config.add_static_view).
            permission = extra.pop('permission', None)
            if permission is None:
                permission = NO_PERMISSION_REQUIRED

            context = extra.pop('context', None)
            if context is None:
                context = extra.pop('for_', None)

            renderer = extra.pop('renderer', None)

            # register a route using the computed view, permission, and
            # pattern, plus any extras passed to us via add_static_view
            pattern = "%s*subpath" % name # name already ends with slash
            if config.route_prefix:
                route_name = '__%s/%s' % (config.route_prefix, name)
            else:
                route_name = '__%s' % name
            config.add_route(route_name, pattern, **extra)
            config.add_view(
                route_name=route_name,
                view=view,
                permission=permission,
                context=context,
                renderer=renderer,
            )

        def register():
            registrations = self.registrations

            names = [t[0] for t in registrations]

            if name in names:
                idx = names.index(name)
                registrations.pop(idx)

            # url, spec, route_name
            registrations.append((url, spec, route_name))

        intr = config.introspectable('static views',
                                     name,
                                     'static view for %r' % name,
                                     'static view')
        intr['name'] = name
        intr['spec'] = spec

        config.action(None, callable=register, introspectables=(intr,))

    def add_cache_buster(self, config, spec, cachebust, explicit=False):
        # ensure the spec always has a trailing slash as we only support
        # adding cache busters to folders, not files
        if os.path.isabs(spec): # FBO windows
            sep = os.sep
        else:
            sep = '/'
        if not spec.endswith(sep) and not spec.endswith(':'):
            spec = spec + sep

        def register():
            if config.registry.settings.get('pyramid.prevent_cachebust'):
                return

            cache_busters = self.cache_busters

            # find duplicate cache buster (old_idx)
            # and insertion location (new_idx)
            new_idx, old_idx = len(cache_busters), None
            for idx, (spec_, cb_, explicit_) in enumerate(cache_busters):
                # if we find an identical (spec, explicit) then use it
                if spec == spec_ and explicit == explicit_:
                    old_idx = new_idx = idx
                    break

                # past all explicit==False specs then add to the end
                elif not explicit and explicit_:
                    new_idx = idx
                    break

                # explicit matches and spec is shorter
                elif explicit == explicit_ and len(spec) < len(spec_):
                    new_idx = idx
                    break

            if old_idx is not None:
                cache_busters.pop(old_idx)

            cache_busters.insert(new_idx, (spec, cachebust, explicit))

        intr = config.introspectable('cache busters',
                                     spec,
                                     'cache buster for %r' % spec,
                                     'cache buster')
        intr['cachebust'] = cachebust
        intr['path'] = spec
        intr['explicit'] = explicit

        config.action(None, callable=register, introspectables=(intr,))

    def _bust_asset_path(self, request, spec, subpath, kw):
        registry = request.registry
        pkg_name, pkg_subpath = resolve_asset_spec(spec)
        rawspec = None

        if pkg_name is not None:
            pathspec = '{0}:{1}{2}'.format(pkg_name, pkg_subpath, subpath)
            overrides = registry.queryUtility(IPackageOverrides, name=pkg_name)
            if overrides is not None:
                resource_name = posixpath.join(pkg_subpath, subpath)
                sources = overrides.filtered_sources(resource_name)
                for source, filtered_path in sources:
                    rawspec = source.get_path(filtered_path)
                    if hasattr(source, 'pkg_name'):
                        rawspec = '{0}:{1}'.format(source.pkg_name, rawspec)
                    break

        else:
            pathspec = pkg_subpath + subpath

        if rawspec is None:
            rawspec = pathspec

        kw['pathspec'] = pathspec
        kw['rawspec'] = rawspec
        for spec_, cachebust, explicit in reversed(self.cache_busters):
            if (
                (explicit and rawspec.startswith(spec_)) or
                (not explicit and pathspec.startswith(spec_))
            ):
                subpath, kw = cachebust(request, subpath, kw)
                break
        return subpath, kw

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user