diff options
| author | Chris McDonough <chrism@plope.com> | 2011-04-27 02:22:29 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-04-27 02:22:29 -0400 |
| commit | b2613a3d8cb16695eb1c465a7cfe5a722942287d (patch) | |
| tree | 7e2942cdd21f497339c3ed5275e1c6e16a800ee6 | |
| parent | 7e655f50decd44ae9118700e5d00d668bab6788c (diff) | |
| parent | 10b8a7120f35497bfea83d2ade2c2915c96861d4 (diff) | |
| download | pyramid-b2613a3d8cb16695eb1c465a7cfe5a722942287d.tar.gz pyramid-b2613a3d8cb16695eb1c465a7cfe5a722942287d.tar.bz2 pyramid-b2613a3d8cb16695eb1c465a7cfe5a722942287d.zip | |
Merge branch 'cguardia-master' into pviews
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | docs/.gitignore | 1 | ||||
| -rw-r--r-- | docs/Makefile | 8 | ||||
| m--------- | docs/_themes | 0 | ||||
| -rw-r--r-- | pyramid/config.py | 30 | ||||
| -rw-r--r-- | pyramid/paster.py | 241 | ||||
| -rw-r--r-- | pyramid/tests/test_config.py | 18 | ||||
| -rw-r--r-- | pyramid/tests/test_paster.py | 444 | ||||
| -rw-r--r-- | requirements.txt | 5 | ||||
| -rw-r--r-- | setup.py | 1 |
10 files changed, 738 insertions, 13 deletions
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..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,5 +84,5 @@ epub: @echo @echo "Build finished. The epub file is in _build/epub." -_themes: - git clone git://github.com/Pylons/pylons_sphinx_theme.git _themes +theme: + cd ..;git submodule update --init;cd docs diff --git a/docs/_themes b/docs/_themes new file mode 160000 +Subproject 53898ec579a1c31e8780824c0a255eca004e0e5 diff --git a/pyramid/config.py b/pyramid/config.py index 3986acba7..9aa7031e0 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -2485,6 +2485,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if xhr: def xhr_predicate(context, request): + """xhr = True""" return request.is_xhr weights.append(1 << 1) predicates.append(xhr_predicate) @@ -2492,6 +2493,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if request_method is not None: def request_method_predicate(context, request): + """request_method = %s""" % request_method return request.method == request_method weights.append(1 << 2) predicates.append(request_method_predicate) @@ -2503,6 +2505,7 @@ 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 weights.append(1 << 3) predicates.append(path_info_predicate) @@ -2512,7 +2515,12 @@ 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) + if request_param_val is None: + msg = "request_param %s" % request_param + else: + msg = "request_param %s = %s" % (request_param, request_param_val) 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 @@ -2529,7 +2537,12 @@ 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) @@ -2542,6 +2555,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if accept is not None: def accept_predicate(context, request): + """accept = %s""" % accept return accept in request.accept weights.append(1 << 6) predicates.append(accept_predicate) @@ -2549,6 +2563,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if containment is not None: def containment_predicate(context, request): + """containment = %s""" % containment return find_interface(context, containment) is not None weights.append(1 << 7) predicates.append(containment_predicate) @@ -2556,6 +2571,7 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if request_type is not None: def request_type_predicate(context, request): + """request_type = %s""" % request_type return request_type.providedBy(request) weights.append(1 << 8) predicates.append(request_type_predicate) @@ -2584,6 +2600,8 @@ def _make_predicates(xhr=None, request_method=None, path_info=None, if custom: for num, predicate in enumerate(custom): + if getattr(predicate, '__doc__', None) is None: + predicate.__doc__ = "<unknown custom predicate>" predicates.append(predicate) # using hash() here rather than id() is intentional: we # want to allow custom predicates that are part of @@ -2698,10 +2716,18 @@ def preserve_view_attrs(view, wrapped_view): except AttributeError: pass try: + wrapped_view.__permission__ = view.__permission__ + except AttributeError: + pass + try: wrapped_view.__predicated__ = view.__predicated__ except AttributeError: pass try: + wrapped_view.__predicates__ = view.__predicates__ + except AttributeError: + pass + try: wrapped_view.__accept__ = view.__accept__ except AttributeError: pass @@ -2786,6 +2812,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 @@ -2836,6 +2863,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 @@ -2858,6 +2886,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 f9f8925d7..15a50458a 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -200,3 +200,244 @@ 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_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 + 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 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 + 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 + + 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__ = list(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', + '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 + if routes_mapper is not None: + 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.environ['bfg.routes.matchdict'] = match + 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 + + # 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) + 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 predicate in predicates: + self.out(" %s" % predicate.__doc__) + + 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 predicate in predicates: + self.out(" %s" % predicate.__doc__) + + 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 = %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.output_multiview_info(view_wrapper) + else: + self.output_view_info(view) + self.out('') + diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py index 560f68f95..f52d194b6 100644 --- a/pyramid/tests/test_config.py +++ b/pyramid/tests/test_config.py @@ -4288,7 +4288,7 @@ class Test__make_predicates(unittest.TestCase): accept='accept', containment='containment', request_type='request_type', - custom=('a',) + custom=(DummyCustomPredicate(),), ) order2, _, _ = self._callFUT( xhr='xhr', @@ -4299,7 +4299,7 @@ class Test__make_predicates(unittest.TestCase): accept='accept', containment='containment', request_type='request_type', - custom=('a',) + custom=(DummyCustomPredicate(),), ) order3, _, _ = self._callFUT( xhr='xhr', @@ -4392,7 +4392,7 @@ class Test__make_predicates(unittest.TestCase): request_type='request_type', ) order9, _, _ = self._callFUT( - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.assertTrue(order1 > order2) self.assertTrue(order2 > order3) @@ -4409,7 +4409,7 @@ class Test__make_predicates(unittest.TestCase): request_method='request_method', ) order2, _, _ = self._callFUT( - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.assertTrue(order1 < order2) @@ -4419,7 +4419,7 @@ class Test__make_predicates(unittest.TestCase): ) order2, _, _ = self._callFUT( request_method='request_method', - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.assertTrue(order1 > order2) @@ -4430,7 +4430,7 @@ class Test__make_predicates(unittest.TestCase): ) order2, _, _ = self._callFUT( request_method='request_method', - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.assertTrue(order1 < order2) @@ -4442,7 +4442,7 @@ class Test__make_predicates(unittest.TestCase): order2, _, _ = self._callFUT( xhr='xhr', request_method='request_method', - custom=('a',), + custom=(DummyCustomPredicate(),), ) self.assertTrue(order1 > order2) @@ -5047,6 +5047,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 d1082fc51..8a5ef7003 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -319,7 +319,423 @@ 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, matchdict={}), + DummyRoute('b', '/b', factory=Factory)] + 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', matchdict={}), + DummyRoute('b', '/a', matchdict={})] + 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', matchdict={}), + DummyRoute('b', '/a', matchdict={})] + 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, 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':{}, '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), + 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':{}, 'route':routes[1]}]) + + def test__find_multi_routes_none_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, []) + + 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 + def predicate(): + """predicate = x""" + view = DummyView(context='context', view_name='a') + view.__predicates__ = [predicate] + 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', matchdict={}) + 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 + def predicate(): + """predicate = x""" + view = DummyView(context='context') + view.__name__ = 'view' + view.__view_attr__ = 'call' + view.__predicates__ = [predicate] + 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 @@ -407,8 +823,34 @@ class DummyMapper(object): return self.routes class DummyRoute(object): - def __init__(self, name, pattern, factory=None): + def __init__(self, name, pattern, factory=None, matchdict=None): self.name = name + self.path = pattern self.pattern = pattern self.factory = factory + self.matchdict = matchdict + self.predicates = [] + + def match(self, route): + return self.matchdict +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 + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..f79a2aab7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +pyramid +zope.configuration +zope.deprecation +zope.component +repoze.sphinx.autointerface @@ -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 """ |
