From 66cda3dbdf336e82b395a8b99e637509e23967bd Mon Sep 17 00:00:00 2001 From: cguardia Date: Sat, 16 Apr 2011 21:51:03 -0500 Subject: start playing with paster command to show matching views for url --- pyramid/config.py | 17 +++++++ pyramid/paster.py | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 1 + 3 files changed, 152 insertions(+) diff --git a/pyramid/config.py b/pyramid/config.py index 9fda75daa..ef520e053 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -2441,6 +2441,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if xhr: def xhr_predicate(context, request): return request.is_xhr + xhr_predicate.__text__ = "XHR = True" weights.append(1 << 1) predicates.append(xhr_predicate) h.update('xhr:%r' % bool(xhr)) @@ -2448,6 +2449,8 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if request_method is not None: def request_method_predicate(context, request): return request.method == request_method + msg = "Request method = %s" + request_method_predicate.__text__ = msg % request_method weights.append(1 << 2) predicates.append(request_method_predicate) h.update('request_method:%r' % request_method) @@ -2459,6 +2462,8 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, raise ConfigurationError(why[0]) def path_info_predicate(context, request): return path_info_val.match(request.path_info) is not None + msg = "path_info = %s" + path_info_predicate.__text__ = msg % path_info weights.append(1 << 3) predicates.append(path_info_predicate) h.update('path_info:%r' % path_info) @@ -2471,6 +2476,11 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if request_param_val is None: return request_param in request.params return request.params.get(request_param) == request_param_val + if request_param_val is None: + msg = "request_param %s" % request_param + else: + msg = "request_param %s = %s" % (request_param, request_param_val) + request_param_predicate.__text__ = msg weights.append(1 << 4) predicates.append(request_param_predicate) h.update('request_param:%r=%r' % (request_param, request_param_val)) @@ -2491,6 +2501,11 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if val is None: return False return header_val.match(val) is not None + if header_val is None: + msg = "header %s" % header_name + else: + msg = "header %s = %s" % (header_name, header_val) + header_predicate.__text__ = msg weights.append(1 << 5) predicates.append(header_predicate) h.update('header:%r=%r' % (header_name, header_val)) @@ -2654,6 +2669,7 @@ def preserve_view_attrs(view, wrapped_view): pass try: wrapped_view.__predicated__ = view.__predicated__ + wrapped_view.__predicates__ = view.__predicates__ except AttributeError: pass try: @@ -2791,6 +2807,7 @@ class ViewDeriver(object): return all((predicate(context, request) for predicate in predicates)) predicate_wrapper.__predicated__ = checker + predicate_wrapper.__predicates__ = predicates return predicate_wrapper @wraps_view diff --git a/pyramid/paster.py b/pyramid/paster.py index bc1573fb8..7ff77522e 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -195,3 +195,137 @@ class PRoutesCommand(PCommand): (IViewClassifier, request_iface, Interface), IView, name='', default=None) self.out(fmt % (route.name, route.pattern, view_callable)) + +class PViewsCommand(PCommand): + """Print, for a given URL, the views that might match. Underneath each + potentially matching route, list the predicates required. Underneath + each route+predicate set, print each view that might match and its + predicates. + + This command accepts three positional arguments: + + ``config_file`` -- specifies the PasteDeploy config file to use + for the interactive shell. + + ``section_name`` -- specifies the section name in the PasteDeploy + config file that represents the application. + + ``url`` -- specifies the URL that will be used to find matching views. + + Example:: + + $ paster proutes myapp.ini main url + + .. note:: You should use a ``section_name`` that refers to the + actual ``app`` section in the config file that points at + your Pyramid app without any middleware wrapping, or this + command will almost certainly fail. + """ + summary = "Print all views in an application that might match a URL" + min_args = 3 + max_args = 3 + stdout = sys.stdout + + parser = Command.standard_parser(simulate=True) + + def out(self, msg): # pragma: no cover + print msg + + def _find_view(self, url, registry): + """ + Accept ``url`` and ``registry``; create a :term:`request` and + find a :app:`Pyramid` view based on introspection of :term:`view + configuration` within the application registry; return the view. + """ + from zope.interface import providedBy + 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 ITraverser + from pyramid.interfaces import IView + from pyramid.interfaces import IViewClassifier + from pyramid.request import Request + from pyramid.traversal import DefaultRootFactory + from pyramid.traversal import ResourceTreeTraverser + + q = registry.queryUtility + root_factory = q(IRootFactory, default=DefaultRootFactory) + routes_mapper = q(IRoutesMapper) + request_factory = q(IRequestFactory, default=Request) + + adapters = registry.adapters + request = 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 + attrs = request.__dict__ + attrs['registry'] = registry + request_iface = IRequest + + # find the root object + root_factory = root_factory + if routes_mapper is not None: + info = routes_mapper(request) + match, route = info['match'], info['route'] + if route is not None: + attrs['matchdict'] = match + attrs['matched_route'] = route + + request_iface = registry.queryUtility( + IRouteRequest, + name=route.name, + default=IRequest) + root_factory = route.factory or root_factory + + root = root_factory(request) + attrs['root'] = root + + # find a context + traverser = adapters.queryAdapter(root, ITraverser) + if traverser is None: + traverser = ResourceTreeTraverser(root) + tdict = traverser(request) + context, view_name, subpath, traversed, vroot, vroot_path =( + tdict['context'], tdict['view_name'], tdict['subpath'], + tdict['traversed'], tdict['virtual_root'], + tdict['virtual_root_path']) + attrs.update(tdict) + + # find a view callable + context_iface = providedBy(context) + view_callable = adapters.lookup( + (IViewClassifier, request_iface, context_iface), + IView, name=view_name, default=None) + + return view_callable + + def command(self): + from pyramid.interfaces import IMultiView + + config_file, section_name, url = self.args + app = self.get_app(config_file, section_name, loadapp=self.loadapp[0]) + registry = app.registry + view = self._find_view(url, registry) + self.out('') + self.out(url) + if IMultiView.providedBy(view): + for dummy, view_wrapper, dummy in view.views: + self.out('') + for p in view_wrapper.__predicates__: + text = getattr(p, '__text__', p.__name__) + self.out(" %s" % text) + self.out(" %s" % str(view_wrapper.__original_view__)) + else: + self.out('') + self.out(view) + diff --git a/setup.py b/setup.py index 7c7c80040..4ab4cca82 100644 --- a/setup.py +++ b/setup.py @@ -85,6 +85,7 @@ setup(name='pyramid', [paste.paster_command] pshell=pyramid.paster:PShellCommand proutes=pyramid.paster:PRoutesCommand + pviews=pyramid.paster:PViewsCommand [console_scripts] bfg2pyramid = pyramid.fixers.fix_bfg_imports:main """ -- cgit v1.2.3 From 94c2dc0bae9cf14cc6a5548119933e4477d07042 Mon Sep 17 00:00:00 2001 From: cguardia Date: Mon, 18 Apr 2011 15:14:24 -0500 Subject: test adding theme as a submodule --- .gitmodules | 3 +++ docs/.gitignore | 1 - docs/Makefile | 3 ++- docs/_themes | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .gitmodules create mode 160000 docs/_themes diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..45397942b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "docs/_themes"] + path = docs/_themes + url = git://github.com/Pylons/pylons_sphinx_theme.git diff --git a/docs/.gitignore b/docs/.gitignore index 1e9e0413c..d4e11e5ea 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,3 +1,2 @@ _build -_themes diff --git a/docs/Makefile b/docs/Makefile index 1d032cf45..3fbf56d0a 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -85,4 +85,5 @@ epub: @echo "Build finished. The epub file is in _build/epub." _themes: - git clone git://github.com/Pylons/pylons_sphinx_theme.git _themes + git submodule init + git submodule update diff --git a/docs/_themes b/docs/_themes new file mode 160000 index 000000000..53898ec57 --- /dev/null +++ b/docs/_themes @@ -0,0 +1 @@ +Subproject commit 53898ec579a1c31e8780824c0a255eca004e0e56 -- cgit v1.2.3 From f2d5cb59deba682d7c1d461ab5e90ba1802d42ac Mon Sep 17 00:00:00 2001 From: cguardia Date: Mon, 18 Apr 2011 21:41:37 -0500 Subject: fixed makefile to update theme submodule correctly --- docs/Makefile | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 3fbf56d0a..21e91d114 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -25,7 +25,7 @@ help: clean: -rm -rf _build/* -html: _themes +html: theme mkdir -p _build/html _build/doctrees $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html @echo @@ -47,7 +47,7 @@ pickle: web: pickle -htmlhelp: _themes +htmlhelp: theme mkdir -p _build/htmlhelp _build/doctrees $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp @echo @@ -84,6 +84,5 @@ epub: @echo @echo "Build finished. The epub file is in _build/epub." -_themes: - git submodule init - git submodule update +theme: + cd ..;git submodule update --init;cd docs -- cgit v1.2.3 From 9c0b0adf505444831704879a00f299ad74837284 Mon Sep 17 00:00:00 2001 From: cguardia Date: Tue, 19 Apr 2011 02:04:30 -0500 Subject: added requirement file to test rtd integration --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..d94f7c98b --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pyramid -- cgit v1.2.3 From 5d150878d489ee90737f3a35e609adbb55de53c3 Mon Sep 17 00:00:00 2001 From: cguardia Date: Tue, 19 Apr 2011 02:15:48 -0500 Subject: changed requirements file to test rtd integration --- requirements.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/requirements.txt b/requirements.txt index d94f7c98b..f79a2aab7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,5 @@ pyramid +zope.configuration +zope.deprecation +zope.component +repoze.sphinx.autointerface -- cgit v1.2.3 From 1b395e6d43b9450ea652d9addb675936b507ea52 Mon Sep 17 00:00:00 2001 From: cguardia Date: Sun, 24 Apr 2011 23:58:32 -0500 Subject: finished paster views command and 100% test coverage --- pyramid/config.py | 21 +- pyramid/paster.py | 158 ++++++++++++--- pyramid/tests/test_config.py | 18 +- pyramid/tests/test_paster.py | 443 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 604 insertions(+), 36 deletions(-) diff --git a/pyramid/config.py b/pyramid/config.py index ef520e053..6206d64c4 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -2441,7 +2441,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if xhr: def xhr_predicate(context, request): return request.is_xhr - xhr_predicate.__text__ = "XHR = True" + xhr_predicate.__text__ = "xhr = True" weights.append(1 << 1) predicates.append(xhr_predicate) h.update('xhr:%r' % bool(xhr)) @@ -2449,7 +2449,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if request_method is not None: def request_method_predicate(context, request): return request.method == request_method - msg = "Request method = %s" + msg = "request method = %s" request_method_predicate.__text__ = msg % request_method weights.append(1 << 2) predicates.append(request_method_predicate) @@ -2513,6 +2513,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if accept is not None: def accept_predicate(context, request): return accept in request.accept + accept_predicate.__text__ = "accept = %s" % accept weights.append(1 << 6) predicates.append(accept_predicate) h.update('accept:%r' % accept) @@ -2520,6 +2521,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if containment is not None: def containment_predicate(context, request): return find_interface(context, containment) is not None + containment_predicate.__text__ = "containment = %s" % containment weights.append(1 << 7) predicates.append(containment_predicate) h.update('containment:%r' % hash(containment)) @@ -2527,6 +2529,8 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if request_type is not None: def request_type_predicate(context, request): return request_type.providedBy(request) + msg = "request type = %s" % request_type + request_type_predicate.__text__ = msg weights.append(1 << 8) predicates.append(request_type_predicate) h.update('request_type:%r' % hash(request_type)) @@ -2545,6 +2549,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, tvalue = tgenerate(m) m['traverse'] = traversal_path(tvalue) return True + traverse_predicate.__text__ = "traverse = True" # This isn't actually a predicate, it's just a infodict # modifier that injects ``traverse`` into the matchdict. As a # result, the ``traverse_predicate`` function above always @@ -2554,6 +2559,8 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if custom: for num, predicate in enumerate(custom): + if not hasattr(predicate, '__text__'): + predicate.__text__ = "custom predicate" predicates.append(predicate) # using hash() here rather than id() is intentional: we # want to allow custom predicates that are part of @@ -2667,9 +2674,14 @@ def preserve_view_attrs(view, wrapped_view): wrapped_view.__call_permissive__ = view.__call_permissive__ except AttributeError: pass + try: + wrapped_view.__permission__ = view.__permission__ + except AttributeError: + pass try: wrapped_view.__predicated__ = view.__predicated__ - wrapped_view.__predicates__ = view.__predicates__ + wrapped_view.__predicates__ = [p.__text__ + for p in view.__predicates__] except AttributeError: pass try: @@ -2757,6 +2769,7 @@ class ViewDeriver(object): raise Forbidden(msg, result) _secured_view.__call_permissive__ = view _secured_view.__permitted__ = _permitted + _secured_view.__permission__ = permission wrapped_view = _secured_view return wrapped_view @@ -2830,6 +2843,8 @@ class ViewDeriver(object): attr_view.__accept__ = accept attr_view.__order__ = order attr_view.__phash__ = phash + attr_view.__view_attr__ = self.kw.get('attr') + attr_view.__permission__ = self.kw.get('permission') return attr_view @wraps_view diff --git a/pyramid/paster.py b/pyramid/paster.py index 7ff77522e..4437db497 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -231,6 +231,17 @@ class PViewsCommand(PCommand): def out(self, msg): # pragma: no cover print msg + def _find_multi_routes(self, mapper, request): + infos = [] + path = request.environ['PATH_INFO'] + # find all routes that match path, regardless of predicates + for route in mapper.get_routes(): + match = route.match(path) + if match is not None: + info = {'match':match, 'route':route} + infos.append(info) + return infos + def _find_view(self, url, registry): """ Accept ``url`` and ``registry``; create a :term:`request` and @@ -238,12 +249,14 @@ class PViewsCommand(PCommand): configuration` within the application registry; return the view. """ from zope.interface import providedBy + from zope.interface import implements 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 ITraverser + from pyramid.interfaces import IMultiView from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.request import Request @@ -258,6 +271,32 @@ class PViewsCommand(PCommand): adapters = registry.adapters request = None + class RoutesMultiView(object): + implements(IMultiView) + + def __init__(self, infos, context_iface, subpath): + self.views = [] + for info in infos: + match, route = info['match'], info['route'] + if route is not None: + request_iface = registry.queryUtility( + IRouteRequest, + name=route.name, + default=IRequest) + view = adapters.lookup( + (IViewClassifier, request_iface, context_iface), + IView, name='', default=None) + if view is None: + continue + view.__predicates__ = [p.__text__ + for p in route.predicates] + view.__route_attrs__ = {'matchdict': match, + 'matched_route': route, + 'subpath': subpath} + view.__view_attr__ = '' + self.views.append((None, view, None)) + + # create the request environ = { 'wsgi.url_scheme':'http', @@ -268,24 +307,28 @@ class PViewsCommand(PCommand): } request = request_factory(environ) context = None + routes_multiview = None attrs = request.__dict__ attrs['registry'] = registry request_iface = IRequest # find the root object - root_factory = root_factory if routes_mapper is not None: - info = routes_mapper(request) - match, route = info['match'], info['route'] - if route is not None: - attrs['matchdict'] = match - attrs['matched_route'] = route - - request_iface = registry.queryUtility( - IRouteRequest, - name=route.name, - default=IRequest) - root_factory = route.factory or root_factory + infos = self._find_multi_routes(routes_mapper, request) + if len(infos) == 1: + info = infos[0] + match, route = info['match'], info['route'] + if route is not None: + attrs['matchdict'] = match + attrs['matched_route'] = route + + request_iface = registry.queryUtility( + IRouteRequest, + name=route.name, + default=IRequest) + root_factory = route.factory or root_factory + if len(infos) > 1: + routes_multiview = infos root = root_factory(request) attrs['root'] = root @@ -303,29 +346,94 @@ class PViewsCommand(PCommand): # find a view callable context_iface = providedBy(context) - view_callable = adapters.lookup( - (IViewClassifier, request_iface, context_iface), - IView, name=view_name, default=None) - - return view_callable + if routes_multiview is None: + view = adapters.lookup( + (IViewClassifier, request_iface, context_iface), + IView, name=view_name, default=None) + else: + view = RoutesMultiView(infos, context_iface, subpath) + + # routes are not registered with a view name + if view is None: + view = adapters.lookup( + (IViewClassifier, request_iface, context_iface), + IView, name='', default=None) + # we don't want a multiview here + if IMultiView.providedBy(view): + view = None + + if view is not None: + view.__request_attrs__ = attrs + + return view + + def output_route_attrs(self, attrs): + if 'matched_route' in attrs: + route = attrs['matched_route'] + self.out(" route name: %s" % route.name) + self.out(" route pattern: %s" % route.pattern) + self.out(" route path: %s" % route.path) + self.out(" subpath: %s" % '/'.join(attrs['subpath'])) + + def output_view_attrs(self, attrs): + self.out(" context: %s" % attrs['context']) + self.out(" view name: %s" % attrs['view_name']) + + def output_multiview_info(self, view_wrapper): + name = view_wrapper.__name__ + module = view_wrapper.__module__ + attr = view_wrapper.__view_attr__ + route_attrs = getattr(view_wrapper, '__route_attrs__', {}) + self.out('') + self.out(" View:") + self.out(" -----") + self.out(" %s.%s.%s" % (module, name, attr)) + self.output_route_attrs(route_attrs) + permission = getattr(view_wrapper, '__permission__', None) + if permission is not None: + self.out(" required permission = %s" % permission) + predicates = getattr(view_wrapper, '__predicates__', None) + if predicates is not None: + for text in predicates: + self.out(" %s" % text) + + def output_view_info(self, view): + if view is not None: + name = getattr(view, '__name__', view.__class__.__name__) + module = view.__module__ + else: + module = 'Not found' + name = '' + self.out('') + self.out(" View:") + self.out(" -----") + self.out(" %s.%s" % (module, name)) + permission = getattr(view, '__permission__', None) + if permission is not None: + self.out(" required permission = %s" % permission) + predicates = getattr(view, '__predicates__', None) + if predicates is not None: + for text in predicates: + self.out(" %s" % text) def command(self): from pyramid.interfaces import IMultiView config_file, section_name, url = self.args + if not url.startswith('/'): + url = '/%s' % url app = self.get_app(config_file, section_name, loadapp=self.loadapp[0]) registry = app.registry view = self._find_view(url, registry) self.out('') - self.out(url) + self.out("URL = %s" % url) + if view is not None: + self.output_view_attrs(view.__request_attrs__) + self.output_route_attrs(view.__request_attrs__) if IMultiView.providedBy(view): for dummy, view_wrapper, dummy in view.views: - self.out('') - for p in view_wrapper.__predicates__: - text = getattr(p, '__text__', p.__name__) - self.out(" %s" % text) - self.out(" %s" % str(view_wrapper.__original_view__)) + self.output_multiview_info(view_wrapper) else: - self.out('') - self.out(view) + self.output_view_info(view) + self.out('') diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py index d2ff65878..d5903d4fb 100644 --- a/pyramid/tests/test_config.py +++ b/pyramid/tests/test_config.py @@ -4218,7 +4218,7 @@ class Test__make_predicates(unittest.TestCase): accept='accept', containment='containment', request_type='request_type', - custom=('a',) + custom=(DummyCustomPredicate(),), ) order2, _, _ = self._callFUT( xhr='xhr', @@ -4229,7 +4229,7 @@ class Test__make_predicates(unittest.TestCase): accept='accept', containment='containment', request_type='request_type', - custom=('a',) + custom=(DummyCustomPredicate(),), ) order3, _, _ = self._callFUT( xhr='xhr', @@ -4322,7 +4322,7 @@ class Test__make_predicates(unittest.TestCase): request_type='request_type', ) order9, _, _ = self._callFUT( - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.failUnless(order1 > order2) self.failUnless(order2 > order3) @@ -4339,7 +4339,7 @@ class Test__make_predicates(unittest.TestCase): request_method='request_method', ) order2, _, _ = self._callFUT( - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.failUnless(order1 < order2) @@ -4349,7 +4349,7 @@ class Test__make_predicates(unittest.TestCase): ) order2, _, _ = self._callFUT( request_method='request_method', - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.failUnless(order1 > order2) @@ -4360,7 +4360,7 @@ class Test__make_predicates(unittest.TestCase): ) order2, _, _ = self._callFUT( request_method='request_method', - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.failUnless(order1 < order2) @@ -4372,7 +4372,7 @@ class Test__make_predicates(unittest.TestCase): order2, _, _ = self._callFUT( xhr='xhr', request_method='request_method', - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.failUnless(order1 > order2) @@ -4977,6 +4977,10 @@ class DummyStaticURLInfo: def add(self, name, spec, **kw): self.added.append((name, spec, kw)) +class DummyCustomPredicate(object): + def __init__(self): + self.__text__ = 'custom predicate' + def dummy_view(request): return 'OK' diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index 35349b7c7..85a79b681 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -248,7 +248,419 @@ class TestPRoutesCommand(unittest.TestCase): result = command._get_mapper(app) self.assertEqual(result.__class__, RoutesMapper) +class TestPViewsCommand(unittest.TestCase): + def _getTargetClass(self): + from pyramid.paster import PViewsCommand + return PViewsCommand + + def _makeOne(self): + return self._getTargetClass()('pviews') + + def test__find_view_no_match(self): + from pyramid.registry import Registry + registry = Registry() + self._register_mapper(registry, []) + command = self._makeOne() + result = command._find_view('/a', registry) + self.assertEqual(result, None) + + def test__find_view_no_match_multiview_registered(self): + from zope.interface import implements + from zope.interface import providedBy + from pyramid.interfaces import IRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IMultiView + from pyramid.traversal import DefaultRootFactory + from pyramid.registry import Registry + registry = Registry() + class View1(object): + implements(IMultiView) + request = DummyRequest({'PATH_INFO':'/a'}) + root = DefaultRootFactory(request) + root_iface = providedBy(root) + registry.registerAdapter(View1(), + (IViewClassifier, IRequest, root_iface), + IMultiView) + self._register_mapper(registry, []) + command = self._makeOne() + result = command._find_view('/x', registry) + self.assertEqual(result, None) + + def test__find_view_traversal(self): + from zope.interface import providedBy + from pyramid.interfaces import IRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + from pyramid.traversal import DefaultRootFactory + from pyramid.registry import Registry + registry = Registry() + def view1(): pass + request = DummyRequest({'PATH_INFO':'/a'}) + root = DefaultRootFactory(request) + root_iface = providedBy(root) + registry.registerAdapter(view1, + (IViewClassifier, IRequest, root_iface), + IView, name='a') + self._register_mapper(registry, []) + command = self._makeOne() + result = command._find_view('/a', registry) + self.assertEqual(result, view1) + + def test__find_view_traversal_multiview(self): + from zope.interface import implements + from zope.interface import providedBy + from pyramid.interfaces import IRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IMultiView + from pyramid.traversal import DefaultRootFactory + from pyramid.registry import Registry + registry = Registry() + class View1(object): + implements(IMultiView) + request = DummyRequest({'PATH_INFO':'/a'}) + root = DefaultRootFactory(request) + root_iface = providedBy(root) + view = View1() + registry.registerAdapter(view, + (IViewClassifier, IRequest, root_iface), + IMultiView, name='a') + self._register_mapper(registry, []) + command = self._makeOne() + result = command._find_view('/a', registry) + self.assertEqual(result, view) + + def test__find_view_route_no_multiview(self): + from zope.interface import Interface + from zope.interface import implements + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + from pyramid.registry import Registry + registry = Registry() + def view():pass + class IMyRoot(Interface): + pass + class IMyRoute(Interface): + pass + registry.registerAdapter(view, + (IViewClassifier, IMyRoute, IMyRoot), + IView, '') + registry.registerUtility(IMyRoute, IRouteRequest, name='a') + class Factory(object): + implements(IMyRoot) + def __init__(self, request): + pass + routes = [DummyRoute('a', '/a', factory=Factory), + DummyRoute('b', '/b', factory=Factory, will_match=False)] + self._register_mapper(registry, routes) + command = self._makeOne() + result = command._find_view('/a', registry) + self.assertEqual(result, view) + + def test__find_view_route_multiview_no_view_registered(self): + from zope.interface import Interface + from zope.interface import implements + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IMultiView + from pyramid.interfaces import IRootFactory + from pyramid.registry import Registry + registry = Registry() + def view1():pass + def view2():pass + class IMyRoot(Interface): + pass + class IMyRoute1(Interface): + pass + class IMyRoute2(Interface): + pass + registry.registerUtility(IMyRoute1, IRouteRequest, name='a') + registry.registerUtility(IMyRoute2, IRouteRequest, name='b') + class Factory(object): + implements(IMyRoot) + def __init__(self, request): + pass + registry.registerUtility(Factory, IRootFactory) + routes = [DummyRoute('a', '/a'), + DummyRoute('b', '/a')] + self._register_mapper(registry, routes) + command = self._makeOne() + result = command._find_view('/a', registry) + self.failUnless(IMultiView.providedBy(result)) + + def test__find_view_route_multiview(self): + from zope.interface import Interface + from zope.interface import implements + from pyramid.interfaces import IRouteRequest + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IView + from pyramid.interfaces import IMultiView + from pyramid.interfaces import IRootFactory + from pyramid.registry import Registry + registry = Registry() + def view1():pass + def view2():pass + class IMyRoot(Interface): + pass + class IMyRoute1(Interface): + pass + class IMyRoute2(Interface): + pass + registry.registerAdapter(view1, + (IViewClassifier, IMyRoute1, IMyRoot), + IView, '') + registry.registerAdapter(view2, + (IViewClassifier, IMyRoute2, IMyRoot), + IView, '') + registry.registerUtility(IMyRoute1, IRouteRequest, name='a') + registry.registerUtility(IMyRoute2, IRouteRequest, name='b') + class Factory(object): + implements(IMyRoot) + def __init__(self, request): + pass + registry.registerUtility(Factory, IRootFactory) + routes = [DummyRoute('a', '/a'), + DummyRoute('b', '/a')] + self._register_mapper(registry, routes) + command = self._makeOne() + result = command._find_view('/a', registry) + self.failUnless(IMultiView.providedBy(result)) + self.assertEqual(len(result.views), 2) + self.failUnless((None, view1, None) in result.views) + self.failUnless((None, view2, None) in result.views) + + def test__find_multi_routes_all_match(self): + command = self._makeOne() + def factory(request): pass + routes = [DummyRoute('a', '/a', factory=factory), + DummyRoute('b', '/a', factory=factory)] + mapper = DummyMapper(*routes) + request = DummyRequest({'PATH_INFO':'/a'}) + result = command._find_multi_routes(mapper, request) + self.assertEqual(result, [{'match':True, 'route':routes[0]}, + {'match':True, 'route':routes[1]}]) + + def test__find_multi_routes_some_match(self): + command = self._makeOne() + def factory(request): pass + routes = [DummyRoute('a', '/a', factory=factory, will_match=False), + DummyRoute('b', '/a', factory=factory)] + mapper = DummyMapper(*routes) + request = DummyRequest({'PATH_INFO':'/a'}) + result = command._find_multi_routes(mapper, request) + self.assertEqual(result, [{'match':True, 'route':routes[1]}]) + + def test__find_multi_routes_none_match(self): + command = self._makeOne() + def factory(request): pass + routes = [DummyRoute('a', '/a', factory=factory, will_match=False), + DummyRoute('b', '/a', factory=factory, will_match=False)] + mapper = DummyMapper(*routes) + request = DummyRequest({'PATH_INFO':'/a'}) + result = command._find_multi_routes(mapper, request) + self.assertEqual(result, []) + def test_views_command_not_found(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + command._find_view = lambda arg1, arg2: None + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[5], ' Not found.') + + def test_views_command_not_found_url_starts_without_slash(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + command._find_view = lambda arg1, arg2: None + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', 'a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[5], ' Not found.') + + def test_views_command_single_view_traversal(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + view = DummyView(context='context', view_name='a') + command._find_view = lambda arg1, arg2: view + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[2], ' context: context') + self.assertEqual(L[3], ' view name: a') + self.assertEqual(L[7], ' pyramid.tests.test_paster.DummyView') + + def test_views_command_single_view_traversal_with_permission(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + view = DummyView(context='context', view_name='a') + view.__permission__ = 'test' + command._find_view = lambda arg1, arg2: view + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[2], ' context: context') + self.assertEqual(L[3], ' view name: a') + self.assertEqual(L[7], ' pyramid.tests.test_paster.DummyView') + self.assertEqual(L[8], ' required permission = test') + + def test_views_command_single_view_traversal_with_predicates(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + view = DummyView(context='context', view_name='a') + view.__predicates__ = ['predicate = x'] + command._find_view = lambda arg1, arg2: view + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[2], ' context: context') + self.assertEqual(L[3], ' view name: a') + self.assertEqual(L[7], ' pyramid.tests.test_paster.DummyView') + self.assertEqual(L[8], ' predicate = x') + + def test_views_command_single_view_route(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + route = DummyRoute('a', '/a') + view = DummyView(context='context', view_name='a', + matched_route=route, subpath='') + command._find_view = lambda arg1, arg2: view + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[2], ' context: context') + self.assertEqual(L[3], ' view name: a') + self.assertEqual(L[4], ' route name: a') + self.assertEqual(L[5], ' route pattern: /a') + self.assertEqual(L[6], ' route path: /a') + self.assertEqual(L[7], ' subpath: ') + self.assertEqual(L[11], ' pyramid.tests.test_paster.DummyView') + + def test_views_command_multiview(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + view = DummyView(context='context') + view.__name__ = 'view' + view.__view_attr__ = 'call' + multiview = DummyMultiView(view, context='context', view_name='a') + command._find_view = lambda arg1, arg2: multiview + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[2], ' context: context') + self.assertEqual(L[3], ' view name: a') + self.assertEqual(L[7], ' pyramid.tests.test_paster.view.call') + + def test_views_command_multiview_with_permission(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + view = DummyView(context='context') + view.__name__ = 'view' + view.__view_attr__ = 'call' + view.__permission__ = 'test' + multiview = DummyMultiView(view, context='context', view_name='a') + command._find_view = lambda arg1, arg2: multiview + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[2], ' context: context') + self.assertEqual(L[3], ' view name: a') + self.assertEqual(L[7], ' pyramid.tests.test_paster.view.call') + self.assertEqual(L[8], ' required permission = test') + + def test_views_command_multiview_with_predicates(self): + from pyramid.registry import Registry + command = self._makeOne() + registry = Registry() + L = [] + command.out = L.append + view = DummyView(context='context') + view.__name__ = 'view' + view.__view_attr__ = 'call' + view.__predicates__ = ['predicate = x'] + multiview = DummyMultiView(view, context='context', view_name='a') + command._find_view = lambda arg1, arg2: multiview + app = DummyApp() + app.registry = registry + loadapp = DummyLoadApp(app) + command.loadapp = (loadapp,) + command.args = ('/foo/bar/myapp.ini', 'myapp', '/a') + result = command.command() + self.assertEqual(result, None) + self.assertEqual(L[1], 'URL = /a') + self.assertEqual(L[2], ' context: context') + self.assertEqual(L[3], ' view name: a') + self.assertEqual(L[7], ' pyramid.tests.test_paster.view.call') + self.assertEqual(L[8], ' predicate = x') + + def _register_mapper(self, registry, routes): + from pyramid.interfaces import IRoutesMapper + mapper = DummyMapper(*routes) + registry.registerUtility(mapper, IRoutesMapper) + class TestGetApp(unittest.TestCase): def _callFUT(self, config_file, section_name, loadapp): from pyramid.paster import get_app @@ -336,8 +748,37 @@ class DummyMapper(object): return self.routes class DummyRoute(object): - def __init__(self, name, pattern, factory=None): + def __init__(self, name, pattern, factory=None, will_match=True): self.name = name + self.path = pattern self.pattern = pattern self.factory = factory + if not will_match: + self.will_match = None + else: + self.will_match = will_match + self.predicates = [] + + def match(self, route): + return self.will_match +class DummyRequest: + application_url = 'http://example.com:5432' + script_name = '' + def __init__(self, environ): + self.environ = environ + self.matchdict = {} + +class DummyView(object): + def __init__(self, **attrs): + self.__request_attrs__ = attrs + +class DummyMultiView(object): + from zope.interface import implements + from pyramid.interfaces import IMultiView + implements(IMultiView) + + def __init__(self, *views, **attrs): + self.views = [(None, view, None) for view in views] + self.__request_attrs__ = attrs + -- cgit v1.2.3 From 10b8a7120f35497bfea83d2ade2c2915c96861d4 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 27 Apr 2011 02:00:30 -0400 Subject: use __doc__ instead of __text__ to represent predicate output; inject bfg.routes.matchdict into environ to prevent return of wrong subpath; expose __predicates__ as actual predicates rather than text for ease of copying (although i dont like it) --- pyramid/config.py | 46 ++++++++++++++++++++--------------------- pyramid/paster.py | 13 ++++++------ pyramid/tests/test_paster.py | 49 ++++++++++++++++++++++---------------------- 3 files changed, 53 insertions(+), 55 deletions(-) diff --git a/pyramid/config.py b/pyramid/config.py index 6206d64c4..a0c3f7a00 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -2440,17 +2440,16 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if xhr: def xhr_predicate(context, request): + """xhr = True""" return request.is_xhr - xhr_predicate.__text__ = "xhr = True" weights.append(1 << 1) predicates.append(xhr_predicate) h.update('xhr:%r' % bool(xhr)) if request_method is not None: def request_method_predicate(context, request): + """request_method = %s""" % request_method return request.method == request_method - msg = "request method = %s" - request_method_predicate.__text__ = msg % request_method weights.append(1 << 2) predicates.append(request_method_predicate) h.update('request_method:%r' % request_method) @@ -2461,9 +2460,8 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, except re.error, why: raise ConfigurationError(why[0]) def path_info_predicate(context, request): + """path_info = %s""" % path_info return path_info_val.match(request.path_info) is not None - msg = "path_info = %s" - path_info_predicate.__text__ = msg % path_info weights.append(1 << 3) predicates.append(path_info_predicate) h.update('path_info:%r' % path_info) @@ -2472,15 +2470,15 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, request_param_val = None if '=' in request_param: request_param, request_param_val = request_param.split('=', 1) - def request_param_predicate(context, request): - if request_param_val is None: - return request_param in request.params - return request.params.get(request_param) == request_param_val if request_param_val is None: msg = "request_param %s" % request_param else: msg = "request_param %s = %s" % (request_param, request_param_val) - request_param_predicate.__text__ = msg + def request_param_predicate(context, request): + """%s""" % msg + if request_param_val is None: + return request_param in request.params + return request.params.get(request_param) == request_param_val weights.append(1 << 4) predicates.append(request_param_predicate) h.update('request_param:%r=%r' % (request_param, request_param_val)) @@ -2494,43 +2492,42 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, header_val = re.compile(header_val) except re.error, why: raise ConfigurationError(why[0]) + if header_val is None: + msg = "header %s" % header_name + else: + msg = "header %s = %s" % (header_name, header_val) def header_predicate(context, request): + """%s""" % msg if header_val is None: return header_name in request.headers val = request.headers.get(header_name) if val is None: return False return header_val.match(val) is not None - if header_val is None: - msg = "header %s" % header_name - else: - msg = "header %s = %s" % (header_name, header_val) - header_predicate.__text__ = msg weights.append(1 << 5) predicates.append(header_predicate) h.update('header:%r=%r' % (header_name, header_val)) if accept is not None: def accept_predicate(context, request): + """accept = %s""" % accept return accept in request.accept - accept_predicate.__text__ = "accept = %s" % accept weights.append(1 << 6) predicates.append(accept_predicate) h.update('accept:%r' % accept) if containment is not None: def containment_predicate(context, request): + """containment = %s""" % containment return find_interface(context, containment) is not None - containment_predicate.__text__ = "containment = %s" % containment weights.append(1 << 7) predicates.append(containment_predicate) h.update('containment:%r' % hash(containment)) if request_type is not None: def request_type_predicate(context, request): + """request_type = %s""" % request_type return request_type.providedBy(request) - msg = "request type = %s" % request_type - request_type_predicate.__text__ = msg weights.append(1 << 8) predicates.append(request_type_predicate) h.update('request_type:%r' % hash(request_type)) @@ -2549,7 +2546,6 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, tvalue = tgenerate(m) m['traverse'] = traversal_path(tvalue) return True - traverse_predicate.__text__ = "traverse = True" # This isn't actually a predicate, it's just a infodict # modifier that injects ``traverse`` into the matchdict. As a # result, the ``traverse_predicate`` function above always @@ -2559,8 +2555,8 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if custom: for num, predicate in enumerate(custom): - if not hasattr(predicate, '__text__'): - predicate.__text__ = "custom predicate" + if getattr(predicate, '__doc__', None) is None: + predicate.__doc__ = "" predicates.append(predicate) # using hash() here rather than id() is intentional: we # want to allow custom predicates that are part of @@ -2680,8 +2676,10 @@ def preserve_view_attrs(view, wrapped_view): pass try: wrapped_view.__predicated__ = view.__predicated__ - wrapped_view.__predicates__ = [p.__text__ - for p in view.__predicates__] + except AttributeError: + pass + try: + wrapped_view.__predicates__ = view.__predicates__ except AttributeError: pass try: diff --git a/pyramid/paster.py b/pyramid/paster.py index 4437db497..a7d813bbc 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -288,8 +288,7 @@ class PViewsCommand(PCommand): IView, name='', default=None) if view is None: continue - view.__predicates__ = [p.__text__ - for p in route.predicates] + view.__predicates__ = list(route.predicates) view.__route_attrs__ = {'matchdict': match, 'matched_route': route, 'subpath': subpath} @@ -321,7 +320,7 @@ class PViewsCommand(PCommand): if route is not None: attrs['matchdict'] = match attrs['matched_route'] = route - + request.environ['bfg.routes.matchdict'] = match request_iface = registry.queryUtility( IRouteRequest, name=route.name, @@ -394,8 +393,8 @@ class PViewsCommand(PCommand): self.out(" required permission = %s" % permission) predicates = getattr(view_wrapper, '__predicates__', None) if predicates is not None: - for text in predicates: - self.out(" %s" % text) + for predicate in predicates: + self.out(" %s" % predicate.__doc__) def output_view_info(self, view): if view is not None: @@ -413,8 +412,8 @@ class PViewsCommand(PCommand): self.out(" required permission = %s" % permission) predicates = getattr(view, '__predicates__', None) if predicates is not None: - for text in predicates: - self.out(" %s" % text) + for predicate in predicates: + self.out(" %s" % predicate.__doc__) def command(self): from pyramid.interfaces import IMultiView diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index 85a79b681..4d7220524 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -350,8 +350,8 @@ class TestPViewsCommand(unittest.TestCase): implements(IMyRoot) def __init__(self, request): pass - routes = [DummyRoute('a', '/a', factory=Factory), - DummyRoute('b', '/b', factory=Factory, will_match=False)] + routes = [DummyRoute('a', '/a', factory=Factory, matchdict={}), + DummyRoute('b', '/b', factory=Factory)] self._register_mapper(registry, routes) command = self._makeOne() result = command._find_view('/a', registry) @@ -380,8 +380,8 @@ class TestPViewsCommand(unittest.TestCase): def __init__(self, request): pass registry.registerUtility(Factory, IRootFactory) - routes = [DummyRoute('a', '/a'), - DummyRoute('b', '/a')] + routes = [DummyRoute('a', '/a', matchdict={}), + DummyRoute('b', '/a', matchdict={})] self._register_mapper(registry, routes) command = self._makeOne() result = command._find_view('/a', registry) @@ -418,8 +418,8 @@ class TestPViewsCommand(unittest.TestCase): def __init__(self, request): pass registry.registerUtility(Factory, IRootFactory) - routes = [DummyRoute('a', '/a'), - DummyRoute('b', '/a')] + routes = [DummyRoute('a', '/a', matchdict={}), + DummyRoute('b', '/a', matchdict={})] self._register_mapper(registry, routes) command = self._makeOne() result = command._find_view('/a', registry) @@ -431,29 +431,29 @@ class TestPViewsCommand(unittest.TestCase): def test__find_multi_routes_all_match(self): command = self._makeOne() def factory(request): pass - routes = [DummyRoute('a', '/a', factory=factory), - DummyRoute('b', '/a', factory=factory)] + routes = [DummyRoute('a', '/a', factory=factory, matchdict={}), + DummyRoute('b', '/a', factory=factory, matchdict={})] mapper = DummyMapper(*routes) request = DummyRequest({'PATH_INFO':'/a'}) result = command._find_multi_routes(mapper, request) - self.assertEqual(result, [{'match':True, 'route':routes[0]}, - {'match':True, 'route':routes[1]}]) + self.assertEqual(result, [{'match':{}, 'route':routes[0]}, + {'match':{}, 'route':routes[1]}]) def test__find_multi_routes_some_match(self): command = self._makeOne() def factory(request): pass - routes = [DummyRoute('a', '/a', factory=factory, will_match=False), - DummyRoute('b', '/a', factory=factory)] + routes = [DummyRoute('a', '/a', factory=factory), + DummyRoute('b', '/a', factory=factory, matchdict={})] mapper = DummyMapper(*routes) request = DummyRequest({'PATH_INFO':'/a'}) result = command._find_multi_routes(mapper, request) - self.assertEqual(result, [{'match':True, 'route':routes[1]}]) + self.assertEqual(result, [{'match':{}, 'route':routes[1]}]) def test__find_multi_routes_none_match(self): command = self._makeOne() def factory(request): pass - routes = [DummyRoute('a', '/a', factory=factory, will_match=False), - DummyRoute('b', '/a', factory=factory, will_match=False)] + routes = [DummyRoute('a', '/a', factory=factory), + DummyRoute('b', '/a', factory=factory)] mapper = DummyMapper(*routes) request = DummyRequest({'PATH_INFO':'/a'}) result = command._find_multi_routes(mapper, request) @@ -541,8 +541,10 @@ class TestPViewsCommand(unittest.TestCase): registry = Registry() L = [] command.out = L.append + def predicate(): + """predicate = x""" view = DummyView(context='context', view_name='a') - view.__predicates__ = ['predicate = x'] + view.__predicates__ = [predicate] command._find_view = lambda arg1, arg2: view app = DummyApp() app.registry = registry @@ -563,7 +565,7 @@ class TestPViewsCommand(unittest.TestCase): registry = Registry() L = [] command.out = L.append - route = DummyRoute('a', '/a') + route = DummyRoute('a', '/a', matchdict={}) view = DummyView(context='context', view_name='a', matched_route=route, subpath='') command._find_view = lambda arg1, arg2: view @@ -637,10 +639,12 @@ class TestPViewsCommand(unittest.TestCase): registry = Registry() L = [] command.out = L.append + def predicate(): + """predicate = x""" view = DummyView(context='context') view.__name__ = 'view' view.__view_attr__ = 'call' - view.__predicates__ = ['predicate = x'] + view.__predicates__ = [predicate] multiview = DummyMultiView(view, context='context', view_name='a') command._find_view = lambda arg1, arg2: multiview app = DummyApp() @@ -748,19 +752,16 @@ class DummyMapper(object): return self.routes class DummyRoute(object): - def __init__(self, name, pattern, factory=None, will_match=True): + def __init__(self, name, pattern, factory=None, matchdict=None): self.name = name self.path = pattern self.pattern = pattern self.factory = factory - if not will_match: - self.will_match = None - else: - self.will_match = will_match + self.matchdict = matchdict self.predicates = [] def match(self, route): - return self.will_match + return self.matchdict class DummyRequest: application_url = 'http://example.com:5432' -- cgit v1.2.3