We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
request object in pviews misses custom request methods
Here’s the setup:
- myapp includes mylib
- `mylib.includeme` calls `add_request_method('user_service_client', get_user_service_client, reify=True)`
- myapp uses traversal; there is a UserCollection with a `__getitem__` method that uses request.user_service_client to see if the user ID is found in our user service.
- under pviews, request.user_service_client does not exist, causing traversal and pviews to fail.

After some interesting diving into pyramid.scripting, pyramid.bootstrap and pyramid.scripts.pviews, I found that bootstrap creates a request object and sets the custom attibutes on it (using the IRequestExtensions utility and _set_extensions method), but PViewsCommand._find_view creates a fresh request object.  Thus, my custom request property is not defined when my resources get this request object.

I changed _find_view to take the request object from bootstrap (it already takes the registry) and my pviews command worked.  21 tests failed because of the changed signature; I don’t know if not creating a fresh request will cause issues for other pviews usecases, but unless someone objects, I’ll make a pull request with this change and fixed tests.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyramid/scripts/pviews.py`
Content:
```
1 import optparse
2 import sys
3 import textwrap
4 
5 from pyramid.interfaces import IMultiView
6 from pyramid.paster import bootstrap
7 from pyramid.scripts.common import parse_vars
8 
9 def main(argv=sys.argv, quiet=False):
10     command = PViewsCommand(argv, quiet)
11     return command.run()
12 
13 class PViewsCommand(object):
14     usage = '%prog config_uri url'
15     description = """\
16     Print, for a given URL, the views that might match. Underneath each
17     potentially matching route, list the predicates required. Underneath
18     each route+predicate set, print each view that might match and its
19     predicates.
20 
21     This command accepts two positional arguments: 'config_uri' specifies the
22     PasteDeploy config file to use for the interactive shell. The format is
23     'inifile#name'. If the name is left off, 'main' will be assumed.  'url'
24     specifies the path info portion of a URL that will be used to find
25     matching views.  Example: 'proutes myapp.ini#main /url'
26     """
27     stdout = sys.stdout
28 
29     parser = optparse.OptionParser(
30         usage,
31         description=textwrap.dedent(description)
32         )
33 
34     bootstrap = (bootstrap,) # testing
35 
36     def __init__(self, argv, quiet=False):
37         self.quiet = quiet
38         self.options, self.args = self.parser.parse_args(argv[1:])
39 
40     def out(self, msg): # pragma: no cover
41         if not self.quiet:
42             print(msg)
43     
44     def _find_multi_routes(self, mapper, request):
45         infos = []
46         path = request.environ['PATH_INFO']
47         # find all routes that match path, regardless of predicates
48         for route in mapper.get_routes():
49             match = route.match(path)
50             if match is not None:
51                 info = {'match':match, 'route':route}
52                 infos.append(info)
53         return infos
54 
55     def _find_view(self, url, registry):
56         """
57         Accept ``url`` and ``registry``; create a :term:`request` and
58         find a :app:`Pyramid` view based on introspection of :term:`view
59         configuration` within the application registry; return the view.
60         """
61         from zope.interface import providedBy
62         from zope.interface import implementer
63         from pyramid.interfaces import IRequest
64         from pyramid.interfaces import IRootFactory
65         from pyramid.interfaces import IRouteRequest
66         from pyramid.interfaces import IRequestFactory
67         from pyramid.interfaces import IRoutesMapper
68         from pyramid.interfaces import IView
69         from pyramid.interfaces import IViewClassifier
70         from pyramid.interfaces import ITraverser
71         from pyramid.request import Request
72         from pyramid.traversal import DefaultRootFactory
73         from pyramid.traversal import ResourceTreeTraverser
74 
75         q = registry.queryUtility
76         root_factory = q(IRootFactory, default=DefaultRootFactory)
77         routes_mapper = q(IRoutesMapper)
78         request_factory = q(IRequestFactory, default=Request)
79 
80         adapters = registry.adapters
81         request = None
82 
83         @implementer(IMultiView)
84         class RoutesMultiView(object):
85 
86             def __init__(self, infos, context_iface, root_factory, request):
87                 self.views = []
88                 for info in infos:
89                     match, route = info['match'], info['route']
90                     if route is not None:
91                         request_iface = registry.queryUtility(
92                             IRouteRequest,
93                             name=route.name,
94                             default=IRequest)
95                         view = adapters.lookup(
96                             (IViewClassifier, request_iface, context_iface),
97                             IView, name='', default=None)
98                         if view is None:
99                             continue
100                         view.__request_attrs__ = {}
101                         view.__request_attrs__['matchdict'] = match
102                         view.__request_attrs__['matched_route'] = route
103                         root_factory = route.factory or root_factory
104                         root = root_factory(request)
105                         traverser = adapters.queryAdapter(root, ITraverser)
106                         if traverser is None:
107                             traverser = ResourceTreeTraverser(root)
108                         tdict = traverser(request)
109                         view.__request_attrs__.update(tdict)
110                         if not hasattr(view, '__view_attr__'):
111                             view.__view_attr__ = ''
112                         self.views.append((None, view, None))
113 
114 
115         # create the request
116         environ = {
117             'wsgi.url_scheme':'http',
118             'SERVER_NAME':'localhost',
119             'SERVER_PORT':'8080',
120             'REQUEST_METHOD':'GET',
121             'PATH_INFO':url,
122             }
123         request = request_factory(environ)
124         context = None
125         routes_multiview = None
126         attrs = request.__dict__
127         attrs['registry'] = registry
128         request_iface = IRequest
129 
130         # find the root object
131         if routes_mapper is not None:
132             infos = self._find_multi_routes(routes_mapper, request)
133             if len(infos) == 1:
134                 info = infos[0]
135                 match, route = info['match'], info['route']
136                 if route is not None:
137                     attrs['matchdict'] = match
138                     attrs['matched_route'] = route
139                     request.environ['bfg.routes.matchdict'] = match
140                     request_iface = registry.queryUtility(
141                         IRouteRequest,
142                         name=route.name,
143                         default=IRequest)
144                     root_factory = route.factory or root_factory
145             if len(infos) > 1:
146                 routes_multiview = infos
147 
148         root = root_factory(request)
149         attrs['root'] = root
150 
151         # find a context
152         traverser = adapters.queryAdapter(root, ITraverser)
153         if traverser is None:
154             traverser = ResourceTreeTraverser(root)
155         tdict = traverser(request)
156         context, view_name, subpath, traversed, vroot, vroot_path =(
157             tdict['context'], tdict['view_name'], tdict['subpath'],
158             tdict['traversed'], tdict['virtual_root'],
159             tdict['virtual_root_path'])
160         attrs.update(tdict)
161 
162         # find a view callable
163         context_iface = providedBy(context)
164         if routes_multiview is None:
165             view = adapters.lookup(
166                 (IViewClassifier, request_iface, context_iface),
167                 IView, name=view_name, default=None)
168         else:
169             view = RoutesMultiView(infos, context_iface, root_factory, request)
170 
171         # routes are not registered with a view name
172         if view is None:
173             view = adapters.lookup(
174                 (IViewClassifier, request_iface, context_iface),
175                 IView, name='', default=None)
176             # we don't want a multiview here
177             if IMultiView.providedBy(view):
178                 view = None
179 
180         if view is not None:
181             view.__request_attrs__ = attrs
182 
183         return view
184 
185     def output_route_attrs(self, attrs, indent):
186         route = attrs['matched_route']
187         self.out("%sroute name: %s" % (indent, route.name))
188         self.out("%sroute pattern: %s" % (indent, route.pattern))
189         self.out("%sroute path: %s" % (indent, route.path))
190         self.out("%ssubpath: %s" % (indent, '/'.join(attrs['subpath'])))
191         predicates = ', '.join([p.text() for p in route.predicates])
192         if predicates != '':
193             self.out("%sroute predicates (%s)" % (indent, predicates))
194 
195     def output_view_info(self, view_wrapper, level=1):
196         indent = "    " * level
197         name = getattr(view_wrapper, '__name__', '')
198         module = getattr(view_wrapper, '__module__', '')
199         attr = getattr(view_wrapper, '__view_attr__', None)
200         request_attrs = getattr(view_wrapper, '__request_attrs__', {})
201         if attr is not None:
202             view_callable = "%s.%s.%s" % (module, name, attr)
203         else:
204             attr = view_wrapper.__class__.__name__
205             if attr == 'function':
206                 attr = name
207             view_callable = "%s.%s" % (module, attr)
208         self.out('')
209         if 'matched_route' in request_attrs:
210             self.out("%sRoute:" % indent)
211             self.out("%s------" % indent)
212             self.output_route_attrs(request_attrs, indent)
213             permission = getattr(view_wrapper, '__permission__', None)
214             if not IMultiView.providedBy(view_wrapper):
215                 # single view for this route, so repeat call without route data
216                 del request_attrs['matched_route']
217                 self.output_view_info(view_wrapper, level+1)
218         else:
219             self.out("%sView:" % indent)
220             self.out("%s-----" % indent)
221             self.out("%s%s" % (indent, view_callable))
222             permission = getattr(view_wrapper, '__permission__', None)
223             if permission is not None:
224                 self.out("%srequired permission = %s" % (indent, permission))
225             predicates = getattr(view_wrapper, '__predicates__', None)
226             if predicates is not None:
227                 predicate_text = ', '.join([p.text() for p in predicates])
228                 self.out("%sview predicates (%s)" % (indent, predicate_text))
229 
230     def run(self):
231         if len(self.args) < 2:
232             self.out('Command requires a config file arg and a url arg')
233             return 2
234         config_uri = self.args[0]
235         url = self.args[1]
236 
237         if not url.startswith('/'):
238             url = '/%s' % url
239         env = self.bootstrap[0](config_uri, options=parse_vars(self.args[2:]))
240         registry = env['registry']
241         view = self._find_view(url, registry)
242         self.out('')
243         self.out("URL = %s" % url)
244         self.out('')
245         if view is not None:
246             self.out("    context: %s" % view.__request_attrs__['context'])
247             self.out("    view name: %s" % view.__request_attrs__['view_name'])
248         if IMultiView.providedBy(view):
249             for dummy, view_wrapper, dummy in view.views:
250                 self.output_view_info(view_wrapper)
251                 if IMultiView.providedBy(view_wrapper):
252                     for dummy, mv_view_wrapper, dummy in view_wrapper.views:
253                         self.output_view_info(mv_view_wrapper, level=2)
254         else:
255             if view is not None:
256                 self.output_view_info(view)
257             else:
258                 self.out("    Not found.")
259         self.out('')
260         return 0
261 
262
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pyramid/scripts/pviews.py b/pyramid/scripts/pviews.py
--- a/pyramid/scripts/pviews.py
+++ b/pyramid/scripts/pviews.py
@@ -4,6 +4,7 @@
 
 from pyramid.interfaces import IMultiView
 from pyramid.paster import bootstrap
+from pyramid.request import Request
 from pyramid.scripts.common import parse_vars
 
 def main(argv=sys.argv, quiet=False):
@@ -52,7 +53,7 @@
                 infos.append(info)
         return infos
 
-    def _find_view(self, url, registry):
+    def _find_view(self, request):
         """
         Accept ``url`` and ``registry``; create a :term:`request` and
         find a :app:`Pyramid` view based on introspection of :term:`view
@@ -63,22 +64,19 @@
         from pyramid.interfaces import IRequest
         from pyramid.interfaces import IRootFactory
         from pyramid.interfaces import IRouteRequest
-        from pyramid.interfaces import IRequestFactory
         from pyramid.interfaces import IRoutesMapper
         from pyramid.interfaces import IView
         from pyramid.interfaces import IViewClassifier
         from pyramid.interfaces import ITraverser
-        from pyramid.request import Request
         from pyramid.traversal import DefaultRootFactory
         from pyramid.traversal import ResourceTreeTraverser
 
+        registry = request.registry
         q = registry.queryUtility
         root_factory = q(IRootFactory, default=DefaultRootFactory)
         routes_mapper = q(IRoutesMapper)
-        request_factory = q(IRequestFactory, default=Request)
 
         adapters = registry.adapters
-        request = None
 
         @implementer(IMultiView)
         class RoutesMultiView(object):
@@ -111,20 +109,9 @@
                             view.__view_attr__ = ''
                         self.views.append((None, view, None))
 
-
-        # create the request
-        environ = {
-            'wsgi.url_scheme':'http',
-            'SERVER_NAME':'localhost',
-            'SERVER_PORT':'8080',
-            'REQUEST_METHOD':'GET',
-            'PATH_INFO':url,
-            }
-        request = request_factory(environ)
         context = None
         routes_multiview = None
         attrs = request.__dict__
-        attrs['registry'] = registry
         request_iface = IRequest
 
         # find the root object
@@ -236,9 +223,10 @@
 
         if not url.startswith('/'):
             url = '/%s' % url
-        env = self.bootstrap[0](config_uri, options=parse_vars(self.args[2:]))
-        registry = env['registry']
-        view = self._find_view(url, registry)
+        request = Request.blank(url)
+        env = self.bootstrap[0](config_uri, options=parse_vars(self.args[2:]),
+                                request=request)
+        view = self._find_view(request)
         self.out('')
         self.out("URL = %s" % url)
         self.out('')
@@ -257,5 +245,6 @@
             else:
                 self.out("    Not found.")
         self.out('')
+        env['closer']()
         return 0

{"golden_diff": "diff --git a/pyramid/scripts/pviews.py b/pyramid/scripts/pviews.py\n--- a/pyramid/scripts/pviews.py\n+++ b/pyramid/scripts/pviews.py\n@@ -4,6 +4,7 @@\n \n from pyramid.interfaces import IMultiView\n from pyramid.paster import bootstrap\n+from pyramid.request import Request\n from pyramid.scripts.common import parse_vars\n \n def main(argv=sys.argv, quiet=False):\n@@ -52,7 +53,7 @@\n                 infos.append(info)\n         return infos\n \n-    def _find_view(self, url, registry):\n+    def _find_view(self, request):\n         \"\"\"\n         Accept ``url`` and ``registry``; create a :term:`request` and\n         find a :app:`Pyramid` view based on introspection of :term:`view\n@@ -63,22 +64,19 @@\n         from pyramid.interfaces import IRequest\n         from pyramid.interfaces import IRootFactory\n         from pyramid.interfaces import IRouteRequest\n-        from pyramid.interfaces import IRequestFactory\n         from pyramid.interfaces import IRoutesMapper\n         from pyramid.interfaces import IView\n         from pyramid.interfaces import IViewClassifier\n         from pyramid.interfaces import ITraverser\n-        from pyramid.request import Request\n         from pyramid.traversal import DefaultRootFactory\n         from pyramid.traversal import ResourceTreeTraverser\n \n+        registry = request.registry\n         q = registry.queryUtility\n         root_factory = q(IRootFactory, default=DefaultRootFactory)\n         routes_mapper = q(IRoutesMapper)\n-        request_factory = q(IRequestFactory, default=Request)\n \n         adapters = registry.adapters\n-        request = None\n \n         @implementer(IMultiView)\n         class RoutesMultiView(object):\n@@ -111,20 +109,9 @@\n                             view.__view_attr__ = ''\n                         self.views.append((None, view, None))\n \n-\n-        # create the request\n-        environ = {\n-            'wsgi.url_scheme':'http',\n-            'SERVER_NAME':'localhost',\n-            'SERVER_PORT':'8080',\n-            'REQUEST_METHOD':'GET',\n-            'PATH_INFO':url,\n-            }\n-        request = request_factory(environ)\n         context = None\n         routes_multiview = None\n         attrs = request.__dict__\n-        attrs['registry'] = registry\n         request_iface = IRequest\n \n         # find the root object\n@@ -236,9 +223,10 @@\n \n         if not url.startswith('/'):\n             url = '/%s' % url\n-        env = self.bootstrap[0](config_uri, options=parse_vars(self.args[2:]))\n-        registry = env['registry']\n-        view = self._find_view(url, registry)\n+        request = Request.blank(url)\n+        env = self.bootstrap[0](config_uri, options=parse_vars(self.args[2:]),\n+                                request=request)\n+        view = self._find_view(request)\n         self.out('')\n         self.out(\"URL = %s\" % url)\n         self.out('')\n@@ -257,5 +245,6 @@\n             else:\n                 self.out(\"    Not found.\")\n         self.out('')\n+        env['closer']()\n         return 0\n", "issue": "request object in pviews misses custom request methods\nHere\u2019s the setup:\n- myapp includes mylib\n- `mylib.includeme` calls `add_request_method('user_service_client', get_user_service_client, reify=True)`\n- myapp uses traversal; there is a UserCollection with a `__getitem__` method that uses request.user_service_client to see if the user ID is found in our user service.\n- under pviews, request.user_service_client does not exist, causing traversal and pviews to fail.\n\nAfter some interesting diving into pyramid.scripting, pyramid.bootstrap and pyramid.scripts.pviews, I found that bootstrap creates a request object and sets the custom attibutes on it (using the IRequestExtensions utility and _set_extensions method), but PViewsCommand._find_view creates a fresh request object.  Thus, my custom request property is not defined when my resources get this request object.\n\nI changed _find_view to take the request object from bootstrap (it already takes the registry) and my pviews command worked.  21 tests failed because of the changed signature; I don\u2019t know if not creating a fresh request will cause issues for other pviews usecases, but unless someone objects, I\u2019ll make a pull request with this change and fixed tests.\n\n", "before_files": [{"content": "import optparse\nimport sys\nimport textwrap\n\nfrom pyramid.interfaces import IMultiView\nfrom pyramid.paster import bootstrap\nfrom pyramid.scripts.common import parse_vars\n\ndef main(argv=sys.argv, quiet=False):\n    command = PViewsCommand(argv, quiet)\n    return command.run()\n\nclass PViewsCommand(object):\n    usage = '%prog config_uri url'\n    description = \"\"\"\\\n    Print, for a given URL, the views that might match. Underneath each\n    potentially matching route, list the predicates required. Underneath\n    each route+predicate set, print each view that might match and its\n    predicates.\n\n    This command accepts two positional arguments: 'config_uri' specifies the\n    PasteDeploy config file to use for the interactive shell. The format is\n    'inifile#name'. If the name is left off, 'main' will be assumed.  'url'\n    specifies the path info portion of a URL that will be used to find\n    matching views.  Example: 'proutes myapp.ini#main /url'\n    \"\"\"\n    stdout = sys.stdout\n\n    parser = optparse.OptionParser(\n        usage,\n        description=textwrap.dedent(description)\n        )\n\n    bootstrap = (bootstrap,) # testing\n\n    def __init__(self, argv, quiet=False):\n        self.quiet = quiet\n        self.options, self.args = self.parser.parse_args(argv[1:])\n\n    def out(self, msg): # pragma: no cover\n        if not self.quiet:\n            print(msg)\n    \n    def _find_multi_routes(self, mapper, request):\n        infos = []\n        path = request.environ['PATH_INFO']\n        # find all routes that match path, regardless of predicates\n        for route in mapper.get_routes():\n            match = route.match(path)\n            if match is not None:\n                info = {'match':match, 'route':route}\n                infos.append(info)\n        return infos\n\n    def _find_view(self, url, registry):\n        \"\"\"\n        Accept ``url`` and ``registry``; create a :term:`request` and\n        find a :app:`Pyramid` view based on introspection of :term:`view\n        configuration` within the application registry; return the view.\n        \"\"\"\n        from zope.interface import providedBy\n        from zope.interface import implementer\n        from pyramid.interfaces import IRequest\n        from pyramid.interfaces import IRootFactory\n        from pyramid.interfaces import IRouteRequest\n        from pyramid.interfaces import IRequestFactory\n        from pyramid.interfaces import IRoutesMapper\n        from pyramid.interfaces import IView\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import ITraverser\n        from pyramid.request import Request\n        from pyramid.traversal import DefaultRootFactory\n        from pyramid.traversal import ResourceTreeTraverser\n\n        q = registry.queryUtility\n        root_factory = q(IRootFactory, default=DefaultRootFactory)\n        routes_mapper = q(IRoutesMapper)\n        request_factory = q(IRequestFactory, default=Request)\n\n        adapters = registry.adapters\n        request = None\n\n        @implementer(IMultiView)\n        class RoutesMultiView(object):\n\n            def __init__(self, infos, context_iface, root_factory, request):\n                self.views = []\n                for info in infos:\n                    match, route = info['match'], info['route']\n                    if route is not None:\n                        request_iface = registry.queryUtility(\n                            IRouteRequest,\n                            name=route.name,\n                            default=IRequest)\n                        view = adapters.lookup(\n                            (IViewClassifier, request_iface, context_iface),\n                            IView, name='', default=None)\n                        if view is None:\n                            continue\n                        view.__request_attrs__ = {}\n                        view.__request_attrs__['matchdict'] = match\n                        view.__request_attrs__['matched_route'] = route\n                        root_factory = route.factory or root_factory\n                        root = root_factory(request)\n                        traverser = adapters.queryAdapter(root, ITraverser)\n                        if traverser is None:\n                            traverser = ResourceTreeTraverser(root)\n                        tdict = traverser(request)\n                        view.__request_attrs__.update(tdict)\n                        if not hasattr(view, '__view_attr__'):\n                            view.__view_attr__ = ''\n                        self.views.append((None, view, None))\n\n\n        # create the request\n        environ = {\n            'wsgi.url_scheme':'http',\n            'SERVER_NAME':'localhost',\n            'SERVER_PORT':'8080',\n            'REQUEST_METHOD':'GET',\n            'PATH_INFO':url,\n            }\n        request = request_factory(environ)\n        context = None\n        routes_multiview = None\n        attrs = request.__dict__\n        attrs['registry'] = registry\n        request_iface = IRequest\n\n        # find the root object\n        if routes_mapper is not None:\n            infos = self._find_multi_routes(routes_mapper, request)\n            if len(infos) == 1:\n                info = infos[0]\n                match, route = info['match'], info['route']\n                if route is not None:\n                    attrs['matchdict'] = match\n                    attrs['matched_route'] = route\n                    request.environ['bfg.routes.matchdict'] = match\n                    request_iface = registry.queryUtility(\n                        IRouteRequest,\n                        name=route.name,\n                        default=IRequest)\n                    root_factory = route.factory or root_factory\n            if len(infos) > 1:\n                routes_multiview = infos\n\n        root = root_factory(request)\n        attrs['root'] = root\n\n        # find a context\n        traverser = adapters.queryAdapter(root, ITraverser)\n        if traverser is None:\n            traverser = ResourceTreeTraverser(root)\n        tdict = traverser(request)\n        context, view_name, subpath, traversed, vroot, vroot_path =(\n            tdict['context'], tdict['view_name'], tdict['subpath'],\n            tdict['traversed'], tdict['virtual_root'],\n            tdict['virtual_root_path'])\n        attrs.update(tdict)\n\n        # find a view callable\n        context_iface = providedBy(context)\n        if routes_multiview is None:\n            view = adapters.lookup(\n                (IViewClassifier, request_iface, context_iface),\n                IView, name=view_name, default=None)\n        else:\n            view = RoutesMultiView(infos, context_iface, root_factory, request)\n\n        # routes are not registered with a view name\n        if view is None:\n            view = adapters.lookup(\n                (IViewClassifier, request_iface, context_iface),\n                IView, name='', default=None)\n            # we don't want a multiview here\n            if IMultiView.providedBy(view):\n                view = None\n\n        if view is not None:\n            view.__request_attrs__ = attrs\n\n        return view\n\n    def output_route_attrs(self, attrs, indent):\n        route = attrs['matched_route']\n        self.out(\"%sroute name: %s\" % (indent, route.name))\n        self.out(\"%sroute pattern: %s\" % (indent, route.pattern))\n        self.out(\"%sroute path: %s\" % (indent, route.path))\n        self.out(\"%ssubpath: %s\" % (indent, '/'.join(attrs['subpath'])))\n        predicates = ', '.join([p.text() for p in route.predicates])\n        if predicates != '':\n            self.out(\"%sroute predicates (%s)\" % (indent, predicates))\n\n    def output_view_info(self, view_wrapper, level=1):\n        indent = \"    \" * level\n        name = getattr(view_wrapper, '__name__', '')\n        module = getattr(view_wrapper, '__module__', '')\n        attr = getattr(view_wrapper, '__view_attr__', None)\n        request_attrs = getattr(view_wrapper, '__request_attrs__', {})\n        if attr is not None:\n            view_callable = \"%s.%s.%s\" % (module, name, attr)\n        else:\n            attr = view_wrapper.__class__.__name__\n            if attr == 'function':\n                attr = name\n            view_callable = \"%s.%s\" % (module, attr)\n        self.out('')\n        if 'matched_route' in request_attrs:\n            self.out(\"%sRoute:\" % indent)\n            self.out(\"%s------\" % indent)\n            self.output_route_attrs(request_attrs, indent)\n            permission = getattr(view_wrapper, '__permission__', None)\n            if not IMultiView.providedBy(view_wrapper):\n                # single view for this route, so repeat call without route data\n                del request_attrs['matched_route']\n                self.output_view_info(view_wrapper, level+1)\n        else:\n            self.out(\"%sView:\" % indent)\n            self.out(\"%s-----\" % indent)\n            self.out(\"%s%s\" % (indent, view_callable))\n            permission = getattr(view_wrapper, '__permission__', None)\n            if permission is not None:\n                self.out(\"%srequired permission = %s\" % (indent, permission))\n            predicates = getattr(view_wrapper, '__predicates__', None)\n            if predicates is not None:\n                predicate_text = ', '.join([p.text() for p in predicates])\n                self.out(\"%sview predicates (%s)\" % (indent, predicate_text))\n\n    def run(self):\n        if len(self.args) < 2:\n            self.out('Command requires a config file arg and a url arg')\n            return 2\n        config_uri = self.args[0]\n        url = self.args[1]\n\n        if not url.startswith('/'):\n            url = '/%s' % url\n        env = self.bootstrap[0](config_uri, options=parse_vars(self.args[2:]))\n        registry = env['registry']\n        view = self._find_view(url, registry)\n        self.out('')\n        self.out(\"URL = %s\" % url)\n        self.out('')\n        if view is not None:\n            self.out(\"    context: %s\" % view.__request_attrs__['context'])\n            self.out(\"    view name: %s\" % view.__request_attrs__['view_name'])\n        if IMultiView.providedBy(view):\n            for dummy, view_wrapper, dummy in view.views:\n                self.output_view_info(view_wrapper)\n                if IMultiView.providedBy(view_wrapper):\n                    for dummy, mv_view_wrapper, dummy in view_wrapper.views:\n                        self.output_view_info(mv_view_wrapper, level=2)\n        else:\n            if view is not None:\n                self.output_view_info(view)\n            else:\n                self.out(\"    Not found.\")\n        self.out('')\n        return 0\n\n", "path": "pyramid/scripts/pviews.py"}], "after_files": [{"content": "import optparse\nimport sys\nimport textwrap\n\nfrom pyramid.interfaces import IMultiView\nfrom pyramid.paster import bootstrap\nfrom pyramid.request import Request\nfrom pyramid.scripts.common import parse_vars\n\ndef main(argv=sys.argv, quiet=False):\n    command = PViewsCommand(argv, quiet)\n    return command.run()\n\nclass PViewsCommand(object):\n    usage = '%prog config_uri url'\n    description = \"\"\"\\\n    Print, for a given URL, the views that might match. Underneath each\n    potentially matching route, list the predicates required. Underneath\n    each route+predicate set, print each view that might match and its\n    predicates.\n\n    This command accepts two positional arguments: 'config_uri' specifies the\n    PasteDeploy config file to use for the interactive shell. The format is\n    'inifile#name'. If the name is left off, 'main' will be assumed.  'url'\n    specifies the path info portion of a URL that will be used to find\n    matching views.  Example: 'proutes myapp.ini#main /url'\n    \"\"\"\n    stdout = sys.stdout\n\n    parser = optparse.OptionParser(\n        usage,\n        description=textwrap.dedent(description)\n        )\n\n    bootstrap = (bootstrap,) # testing\n\n    def __init__(self, argv, quiet=False):\n        self.quiet = quiet\n        self.options, self.args = self.parser.parse_args(argv[1:])\n\n    def out(self, msg): # pragma: no cover\n        if not self.quiet:\n            print(msg)\n    \n    def _find_multi_routes(self, mapper, request):\n        infos = []\n        path = request.environ['PATH_INFO']\n        # find all routes that match path, regardless of predicates\n        for route in mapper.get_routes():\n            match = route.match(path)\n            if match is not None:\n                info = {'match':match, 'route':route}\n                infos.append(info)\n        return infos\n\n    def _find_view(self, request):\n        \"\"\"\n        Accept ``url`` and ``registry``; create a :term:`request` and\n        find a :app:`Pyramid` view based on introspection of :term:`view\n        configuration` within the application registry; return the view.\n        \"\"\"\n        from zope.interface import providedBy\n        from zope.interface import implementer\n        from pyramid.interfaces import IRequest\n        from pyramid.interfaces import IRootFactory\n        from pyramid.interfaces import IRouteRequest\n        from pyramid.interfaces import IRoutesMapper\n        from pyramid.interfaces import IView\n        from pyramid.interfaces import IViewClassifier\n        from pyramid.interfaces import ITraverser\n        from pyramid.traversal import DefaultRootFactory\n        from pyramid.traversal import ResourceTreeTraverser\n\n        registry = request.registry\n        q = registry.queryUtility\n        root_factory = q(IRootFactory, default=DefaultRootFactory)\n        routes_mapper = q(IRoutesMapper)\n\n        adapters = registry.adapters\n\n        @implementer(IMultiView)\n        class RoutesMultiView(object):\n\n            def __init__(self, infos, context_iface, root_factory, request):\n                self.views = []\n                for info in infos:\n                    match, route = info['match'], info['route']\n                    if route is not None:\n                        request_iface = registry.queryUtility(\n                            IRouteRequest,\n                            name=route.name,\n                            default=IRequest)\n                        view = adapters.lookup(\n                            (IViewClassifier, request_iface, context_iface),\n                            IView, name='', default=None)\n                        if view is None:\n                            continue\n                        view.__request_attrs__ = {}\n                        view.__request_attrs__['matchdict'] = match\n                        view.__request_attrs__['matched_route'] = route\n                        root_factory = route.factory or root_factory\n                        root = root_factory(request)\n                        traverser = adapters.queryAdapter(root, ITraverser)\n                        if traverser is None:\n                            traverser = ResourceTreeTraverser(root)\n                        tdict = traverser(request)\n                        view.__request_attrs__.update(tdict)\n                        if not hasattr(view, '__view_attr__'):\n                            view.__view_attr__ = ''\n                        self.views.append((None, view, None))\n\n        context = None\n        routes_multiview = None\n        attrs = request.__dict__\n        request_iface = IRequest\n\n        # find the root object\n        if routes_mapper is not None:\n            infos = self._find_multi_routes(routes_mapper, request)\n            if len(infos) == 1:\n                info = infos[0]\n                match, route = info['match'], info['route']\n                if route is not None:\n                    attrs['matchdict'] = match\n                    attrs['matched_route'] = route\n                    request.environ['bfg.routes.matchdict'] = match\n                    request_iface = registry.queryUtility(\n                        IRouteRequest,\n                        name=route.name,\n                        default=IRequest)\n                    root_factory = route.factory or root_factory\n            if len(infos) > 1:\n                routes_multiview = infos\n\n        root = root_factory(request)\n        attrs['root'] = root\n\n        # find a context\n        traverser = adapters.queryAdapter(root, ITraverser)\n        if traverser is None:\n            traverser = ResourceTreeTraverser(root)\n        tdict = traverser(request)\n        context, view_name, subpath, traversed, vroot, vroot_path =(\n            tdict['context'], tdict['view_name'], tdict['subpath'],\n            tdict['traversed'], tdict['virtual_root'],\n            tdict['virtual_root_path'])\n        attrs.update(tdict)\n\n        # find a view callable\n        context_iface = providedBy(context)\n        if routes_multiview is None:\n            view = adapters.lookup(\n                (IViewClassifier, request_iface, context_iface),\n                IView, name=view_name, default=None)\n        else:\n            view = RoutesMultiView(infos, context_iface, root_factory, request)\n\n        # routes are not registered with a view name\n        if view is None:\n            view = adapters.lookup(\n                (IViewClassifier, request_iface, context_iface),\n                IView, name='', default=None)\n            # we don't want a multiview here\n            if IMultiView.providedBy(view):\n                view = None\n\n        if view is not None:\n            view.__request_attrs__ = attrs\n\n        return view\n\n    def output_route_attrs(self, attrs, indent):\n        route = attrs['matched_route']\n        self.out(\"%sroute name: %s\" % (indent, route.name))\n        self.out(\"%sroute pattern: %s\" % (indent, route.pattern))\n        self.out(\"%sroute path: %s\" % (indent, route.path))\n        self.out(\"%ssubpath: %s\" % (indent, '/'.join(attrs['subpath'])))\n        predicates = ', '.join([p.text() for p in route.predicates])\n        if predicates != '':\n            self.out(\"%sroute predicates (%s)\" % (indent, predicates))\n\n    def output_view_info(self, view_wrapper, level=1):\n        indent = \"    \" * level\n        name = getattr(view_wrapper, '__name__', '')\n        module = getattr(view_wrapper, '__module__', '')\n        attr = getattr(view_wrapper, '__view_attr__', None)\n        request_attrs = getattr(view_wrapper, '__request_attrs__', {})\n        if attr is not None:\n            view_callable = \"%s.%s.%s\" % (module, name, attr)\n        else:\n            attr = view_wrapper.__class__.__name__\n            if attr == 'function':\n                attr = name\n            view_callable = \"%s.%s\" % (module, attr)\n        self.out('')\n        if 'matched_route' in request_attrs:\n            self.out(\"%sRoute:\" % indent)\n            self.out(\"%s------\" % indent)\n            self.output_route_attrs(request_attrs, indent)\n            permission = getattr(view_wrapper, '__permission__', None)\n            if not IMultiView.providedBy(view_wrapper):\n                # single view for this route, so repeat call without route data\n                del request_attrs['matched_route']\n                self.output_view_info(view_wrapper, level+1)\n        else:\n            self.out(\"%sView:\" % indent)\n            self.out(\"%s-----\" % indent)\n            self.out(\"%s%s\" % (indent, view_callable))\n            permission = getattr(view_wrapper, '__permission__', None)\n            if permission is not None:\n                self.out(\"%srequired permission = %s\" % (indent, permission))\n            predicates = getattr(view_wrapper, '__predicates__', None)\n            if predicates is not None:\n                predicate_text = ', '.join([p.text() for p in predicates])\n                self.out(\"%sview predicates (%s)\" % (indent, predicate_text))\n\n    def run(self):\n        if len(self.args) < 2:\n            self.out('Command requires a config file arg and a url arg')\n            return 2\n        config_uri = self.args[0]\n        url = self.args[1]\n\n        if not url.startswith('/'):\n            url = '/%s' % url\n        request = Request.blank(url)\n        env = self.bootstrap[0](config_uri, options=parse_vars(self.args[2:]),\n                                request=request)\n        view = self._find_view(request)\n        self.out('')\n        self.out(\"URL = %s\" % url)\n        self.out('')\n        if view is not None:\n            self.out(\"    context: %s\" % view.__request_attrs__['context'])\n            self.out(\"    view name: %s\" % view.__request_attrs__['view_name'])\n        if IMultiView.providedBy(view):\n            for dummy, view_wrapper, dummy in view.views:\n                self.output_view_info(view_wrapper)\n                if IMultiView.providedBy(view_wrapper):\n                    for dummy, mv_view_wrapper, dummy in view_wrapper.views:\n                        self.output_view_info(mv_view_wrapper, level=2)\n        else:\n            if view is not None:\n                self.output_view_info(view)\n            else:\n                self.out(\"    Not found.\")\n        self.out('')\n        env['closer']()\n        return 0\n\n", "path": "pyramid/scripts/pviews.py"}]}