Remove configurator.add_handler, handler-related functions and methods from pyramid.view, handler ZCML directive. This functionality is to be moved to a "pyramid_handlers" package.
Fix add_directive to properly persist directives across configurator creations.
| | |
| | | - URL Dispatch properly handles a '.*' or '*' appearing in a regex match |
| | | when used inside brackets. Resolve Issue #90. |
| | | |
| | | Backwards Incompatibilities |
| | | --------------------------- |
| | | |
| | | - The ``add_handler`` method of a Configurator has been removed from the |
| | | Pyramid core. Handlers are now a feature of the ``pyramid_handlers`` |
| | | package, which can be downloaded from PyPI. Documentation for the package |
| | | should be available via http://pylonsproject.org, which describes how to |
| | | get this method back after depending upon ``pyramid_handlers`` as an |
| | | ``install_requires`` dependency. |
| | | |
| | | - The ``pyramid.view.action`` decorator has been removed from the Pyramid |
| | | core. Handlers are now a feature of the ``pyramid_handlers`` package. It |
| | | should now be imported from ``pyramid_handlers`` e.g. ``from |
| | | pyramid_handlers import action``. |
| | | |
| | | - The ``handler`` ZCML directive has been removed. It is now a feature of |
| | | the ``pyramid_handlers`` package. |
| | | |
| | | Features |
| | | -------- |
| | | |
| | |
| | | |
| | | .. automethod:: add_translation_dirs |
| | | |
| | | .. automethod:: add_handler |
| | | |
| | | .. automethod:: add_view |
| | | |
| | | .. automethod:: derive_view |
| | |
| | | zcml/configure |
| | | zcml/default_permission |
| | | zcml/forbidden |
| | | zcml/handler |
| | | zcml/include |
| | | zcml/localenegotiator |
| | | zcml/notfound |
| | |
| | | session_factory=session_factory, |
| | | default_view_mapper=default_view_mapper, |
| | | ) |
| | | if hasattr(registry, '_directives'): |
| | | for name, directive in registry._directives.items(): |
| | | self.add_directive(name, directive) |
| | | |
| | | def _set_settings(self, mapping): |
| | | settings = Settings(mapping or {}) |
| | |
| | | if not hasattr(self.registry, '_directives'): |
| | | self.registry._directives = {} |
| | | self.registry._directives[name] = c |
| | | |
| | | def __getattr__(self, name): |
| | | # allow directive extension names to work |
| | | directives = getattr(self.registry, '_directives', {}) |
| | | c = directives.get(name) |
| | | if c is None: |
| | | raise AttributeError(name) |
| | | c = action_method(c) |
| | | m = types.MethodType(c, self, self.__class__) |
| | | setattr(self, name, m) |
| | | return m |
| | | |
| | | @classmethod |
| | | def with_context(cls, context): |
| | |
| | | lock.release() |
| | | self.manager.pop() |
| | | return registry |
| | | |
| | | @action_method |
| | | def add_handler(self, route_name, pattern, handler, action=None, **kw): |
| | | |
| | | """ Add a Pylons-style view handler. This function adds a |
| | | route and some number of views based on a handler object |
| | | (usually a class). |
| | | |
| | | ``route_name`` is the name of the route (to be used later in |
| | | URL generation). |
| | | |
| | | ``pattern`` is the matching pattern, |
| | | e.g. ``'/blog/{action}'``. ``pattern`` may be ``None``, in |
| | | which case the pattern of an existing route named the same as |
| | | ``route_name`` is used. If ``pattern`` is ``None`` and no |
| | | route named ``route_name`` exists, a ``ConfigurationError`` is |
| | | raised. |
| | | |
| | | ``handler`` is a dotted name of (or direct reference to) a |
| | | Python handler class, |
| | | e.g. ``'my.package.handlers.MyHandler'``. |
| | | |
| | | If ``{action}`` or ``:action`` is in |
| | | the pattern, the exposed methods of the handler will be used |
| | | as views. |
| | | |
| | | If ``action`` is passed, it will be considered the method name |
| | | of the handler to use as a view. |
| | | |
| | | Passing both ``action`` and having an ``{action}`` in the |
| | | route pattern is disallowed. |
| | | |
| | | Any extra keyword arguments are passed along to ``add_route``. |
| | | |
| | | See :ref:`views_chapter` for more explanatory documentation. |
| | | |
| | | This method returns the result of add_route.""" |
| | | handler = self.maybe_dotted(handler) |
| | | |
| | | if pattern is not None: |
| | | route = self.add_route(route_name, pattern, **kw) |
| | | else: |
| | | mapper = self.get_routes_mapper() |
| | | route = mapper.get_route(route_name) |
| | | if route is None: |
| | | raise ConfigurationError( |
| | | 'The "pattern" parameter may only be "None" when a route ' |
| | | 'with the route_name argument was previously registered. ' |
| | | 'No such route named %r exists' % route_name) |
| | | |
| | | pattern = route.pattern |
| | | |
| | | action_decorator = getattr(handler, '__action_decorator__', None) |
| | | if action_decorator is not None: |
| | | if hasattr(action_decorator, 'im_self'): |
| | | # instance methods have an im_self == None |
| | | # classmethods have an im_self == cls |
| | | # staticmethods have no im_self |
| | | # instances have no im_self |
| | | if action_decorator.im_self is not handler: |
| | | raise ConfigurationError( |
| | | 'The "__action_decorator__" attribute of a handler ' |
| | | 'must not be an instance method (must be a ' |
| | | 'staticmethod, classmethod, function, or an instance ' |
| | | 'which is a callable') |
| | | |
| | | path_has_action = ':action' in pattern or '{action}' in pattern |
| | | |
| | | if action and path_has_action: |
| | | raise ConfigurationError( |
| | | 'action= (%r) disallowed when an action is in the route ' |
| | | 'path %r' % (action, pattern)) |
| | | |
| | | if path_has_action: |
| | | autoexpose = getattr(handler, '__autoexpose__', r'[A-Za-z]+') |
| | | if autoexpose: |
| | | try: |
| | | autoexpose = re.compile(autoexpose).match |
| | | except (re.error, TypeError), why: |
| | | raise ConfigurationError(why[0]) |
| | | for method_name, method in inspect.getmembers( |
| | | handler, inspect.ismethod): |
| | | configs = getattr(method, '__exposed__', []) |
| | | if autoexpose and not configs: |
| | | if autoexpose(method_name): |
| | | configs = [{}] |
| | | for expose_config in configs: |
| | | # we don't want to mutate any dict in __exposed__, |
| | | # so we copy each |
| | | view_args = expose_config.copy() |
| | | action = view_args.pop('name', method_name) |
| | | preds = list(view_args.pop('custom_predicates', [])) |
| | | preds.append(ActionPredicate(action)) |
| | | view_args['custom_predicates'] = preds |
| | | self.add_view(view=handler, attr=method_name, |
| | | route_name=route_name, |
| | | decorator=action_decorator, **view_args) |
| | | else: |
| | | method_name = action |
| | | if method_name is None: |
| | | method_name = '__call__' |
| | | |
| | | # Scan the controller for any other methods with this action name |
| | | for meth_name, method in inspect.getmembers( |
| | | handler, inspect.ismethod): |
| | | configs = getattr(method, '__exposed__', [{}]) |
| | | for expose_config in configs: |
| | | # Don't re-register the same view if this method name is |
| | | # the action name |
| | | if meth_name == action: |
| | | continue |
| | | # We only reg a view if the name matches the action |
| | | if expose_config.get('name') != method_name: |
| | | continue |
| | | # we don't want to mutate any dict in __exposed__, |
| | | # so we copy each |
| | | view_args = expose_config.copy() |
| | | del view_args['name'] |
| | | self.add_view(view=handler, attr=meth_name, |
| | | route_name=route_name, |
| | | decorator=action_decorator, **view_args) |
| | | |
| | | # Now register the method itself |
| | | method = getattr(handler, method_name, None) |
| | | configs = getattr(method, '__exposed__', [{}]) |
| | | for expose_config in configs: |
| | | self.add_view(view=handler, attr=action, route_name=route_name, |
| | | decorator=action_decorator, **expose_config) |
| | | |
| | | return route |
| | | |
| | | @action_method |
| | | def add_view(self, view=None, name="", for_=None, permission=None, |
| | |
| | | return True |
| | | |
| | | return False |
| | | |
| | | |
| | | class ActionPredicate(object): |
| | | action_name = 'action' |
| | | def __init__(self, action): |
| | | self.action = action |
| | | try: |
| | | self.action_re = re.compile(action + '$') |
| | | except (re.error, TypeError), why: |
| | | raise ConfigurationError(why[0]) |
| | | |
| | | def __call__(self, context, request): |
| | | matchdict = request.matchdict |
| | | if matchdict is None: |
| | | return False |
| | | action = matchdict.get(self.action_name) |
| | | if action is None: |
| | | return False |
| | | return bool(self.action_re.match(action)) |
| | | |
| | | def __hash__(self): |
| | | # allow this predicate's phash to be compared as equal to |
| | | # others that share the same action name |
| | | return hash(self.action) |
| | | |
| | | class PyramidConfigurationMachine(ConfigurationMachine): |
| | | autocommit = False |
| | |
| | | /> |
| | | |
| | | <meta:directive |
| | | name="handler" |
| | | schema="pyramid.zcml.IHandlerDirective" |
| | | handler="pyramid.zcml.handler" |
| | | /> |
| | | |
| | | <meta:directive |
| | | name="asset" |
| | | schema="pyramid.zcml.IAssetDirective" |
| | | handler="pyramid.zcml.asset" |
| | |
| | | request = self._makeRequest(config) |
| | | self.assertEqual(view(None, request), 'OK') |
| | | |
| | | def test_add_handler_action_in_route_pattern(self): |
| | | config = self._makeOne(autocommit=True) |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | config.add_handler('name', '/:action', DummyHandler) |
| | | self._assertRoute(config, 'name', '/:action', 0) |
| | | self.assertEqual(len(views), 2) |
| | | |
| | | view = views[0] |
| | | preds = view['custom_predicates'] |
| | | self.assertEqual(len(preds), 1) |
| | | pred = preds[0] |
| | | request = DummyRequest() |
| | | self.assertEqual(pred(None, request), False) |
| | | request.matchdict = {'action':'action1'} |
| | | self.assertEqual(pred(None, request), True) |
| | | self.assertEqual(view['route_name'], 'name') |
| | | self.assertEqual(view['attr'], 'action1') |
| | | self.assertEqual(view['view'], DummyHandler) |
| | | |
| | | view = views[1] |
| | | preds = view['custom_predicates'] |
| | | self.assertEqual(len(preds), 1) |
| | | pred = preds[0] |
| | | request = DummyRequest() |
| | | self.assertEqual(pred(None, request), False) |
| | | request.matchdict = {'action':'action2'} |
| | | self.assertEqual(pred(None, request), True) |
| | | self.assertEqual(view['route_name'], 'name') |
| | | self.assertEqual(view['attr'], 'action2') |
| | | self.assertEqual(view['view'], DummyHandler) |
| | | |
| | | def test_add_handler_with_view_overridden_autoexpose_None(self): |
| | | config = self._makeOne(autocommit=True) |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) # pragma: no cover |
| | | config.add_view = dummy_add_view |
| | | class MyView(DummyHandler): |
| | | __autoexpose__ = None |
| | | config.add_handler('name', '/:action', MyView) |
| | | self._assertRoute(config, 'name', '/:action', 0) |
| | | self.assertEqual(len(views), 0) |
| | | |
| | | def test_add_handler_with_view_overridden_autoexpose_broken_regex1(self): |
| | | from pyramid.exceptions import ConfigurationError |
| | | config = self._makeOne() |
| | | def dummy_add_view(**kw): |
| | | """ """ |
| | | config.add_view = dummy_add_view |
| | | class MyView(DummyHandler): |
| | | __autoexpose__ = 1 |
| | | self.assertRaises(ConfigurationError, config.add_handler, |
| | | 'name', '/{action}', MyView) |
| | | |
| | | def test_add_handler_with_view_overridden_autoexpose_broken_regex2(self): |
| | | from pyramid.exceptions import ConfigurationError |
| | | config = self._makeOne() |
| | | def dummy_add_view(**kw): |
| | | """ """ |
| | | config.add_view = dummy_add_view |
| | | class MyView(DummyHandler): |
| | | __autoexpose__ = 'a\\' |
| | | self.assertRaises(ConfigurationError, config.add_handler, |
| | | 'name', '/{action}', MyView) |
| | | |
| | | def test_add_handler_with_view_method_has_expose_config(self): |
| | | config = self._makeOne(autocommit=True) |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | class MyView(object): |
| | | def action(self): # pragma: no cover |
| | | return 'response' |
| | | action.__exposed__ = [{'custom_predicates':(1,)}] |
| | | config.add_handler('name', '/:action', MyView) |
| | | self._assertRoute(config, 'name', '/:action', 0) |
| | | self.assertEqual(len(views), 1) |
| | | view = views[0] |
| | | preds = view['custom_predicates'] |
| | | self.assertEqual(len(preds), 2) |
| | | self.assertEqual(view['route_name'], 'name') |
| | | self.assertEqual(view['attr'], 'action') |
| | | self.assertEqual(view['view'], MyView) |
| | | |
| | | def test_add_handler_with_view_method_has_expose_config_with_action(self): |
| | | config = self._makeOne(autocommit=True) |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | class MyView(object): |
| | | def action(self): # pragma: no cover |
| | | return 'response' |
| | | action.__exposed__ = [{'name':'action3000'}] |
| | | config.add_handler('name', '/:action', MyView) |
| | | self._assertRoute(config, 'name', '/:action', 0) |
| | | self.assertEqual(len(views), 1) |
| | | view = views[0] |
| | | preds = view['custom_predicates'] |
| | | self.assertEqual(len(preds), 1) |
| | | pred = preds[0] |
| | | request = DummyRequest() |
| | | self.assertEqual(pred(None, request), False) |
| | | request.matchdict = {'action':'action3000'} |
| | | self.assertEqual(pred(None, request), True) |
| | | self.assertEqual(view['route_name'], 'name') |
| | | self.assertEqual(view['attr'], 'action') |
| | | self.assertEqual(view['view'], MyView) |
| | | |
| | | def test_add_handler_with_view_method_has_expose_config_with_action_regex( |
| | | self): |
| | | config = self._makeOne(autocommit=True) |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | class MyView(object): |
| | | def action(self): # pragma: no cover |
| | | return 'response' |
| | | action.__exposed__ = [{'name':'^action3000$'}] |
| | | config.add_handler('name', '/:action', MyView) |
| | | self._assertRoute(config, 'name', '/:action', 0) |
| | | self.assertEqual(len(views), 1) |
| | | view = views[0] |
| | | preds = view['custom_predicates'] |
| | | self.assertEqual(len(preds), 1) |
| | | pred = preds[0] |
| | | request = DummyRequest() |
| | | self.assertEqual(pred(None, request), False) |
| | | request.matchdict = {'action':'action3000'} |
| | | self.assertEqual(pred(None, request), True) |
| | | self.assertEqual(view['route_name'], 'name') |
| | | self.assertEqual(view['attr'], 'action') |
| | | self.assertEqual(view['view'], MyView) |
| | | |
| | | def test_add_handler_with_action_decorator(self): |
| | | config = self._makeOne(autocommit=True) |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | class MyHandler(object): |
| | | @classmethod |
| | | def __action_decorator__(cls, fn): # pragma: no cover |
| | | return fn |
| | | def action(self): # pragma: no cover |
| | | return 'response' |
| | | config.add_handler('name', '/{action}', MyHandler) |
| | | self.assertEqual(len(views), 1) |
| | | self.assertEqual(views[0]['decorator'], MyHandler.__action_decorator__) |
| | | |
| | | def test_add_handler_with_action_decorator_fail_on_instancemethod(self): |
| | | config = self._makeOne(autocommit=True) |
| | | class MyHandler(object): |
| | | def __action_decorator__(self, fn): # pragma: no cover |
| | | return fn |
| | | def action(self): # pragma: no cover |
| | | return 'response' |
| | | from pyramid.exceptions import ConfigurationError |
| | | self.assertRaises(ConfigurationError, config.add_handler, |
| | | 'name', '/{action}', MyHandler) |
| | | |
| | | def test_add_handler_doesnt_mutate_expose_dict(self): |
| | | config = self._makeOne(autocommit=True) |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | exposed = [{'name':'^action3000$'}] |
| | | class MyView(object): |
| | | def action(self): # pragma: no cover |
| | | return 'response' |
| | | action.__exposed__ = exposed |
| | | config.add_handler('name', '/{action}', MyView) |
| | | self.assertEqual(exposed[0], {'name':'^action3000$'}) # not mutated |
| | | |
| | | def test_add_handler_with_action_and_action_in_path(self): |
| | | from pyramid.exceptions import ConfigurationError |
| | | config = self._makeOne() |
| | | self.assertRaises(ConfigurationError, config.add_handler, |
| | | 'name', '/{action}', DummyHandler, action='abc') |
| | | |
| | | def test_add_handler_with_explicit_action(self): |
| | | config = self._makeOne(autocommit=True) |
| | | class DummyHandler(object): |
| | | def index(self): pass |
| | | index.__exposed__ = [{'a':'1'}] |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | config.add_handler('name', '/abc', DummyHandler, action='index') |
| | | self.assertEqual(len(views), 1) |
| | | view = views[0] |
| | | self.assertEqual(view['a'], '1') |
| | | self.assertEqual(view['attr'], 'index') |
| | | self.assertEqual(view['route_name'], 'name') |
| | | self.assertEqual(view['view'], DummyHandler) |
| | | |
| | | def test_add_handler_with_implicit_action(self): |
| | | config = self._makeOne(autocommit=True) |
| | | class DummyHandler(object): |
| | | def __call__(self): pass |
| | | __call__.__exposed__ = [{'a':'1'}] |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | config.add_handler('name', '/abc', DummyHandler) |
| | | self.assertEqual(len(views), 1) |
| | | view = views[0] |
| | | self.assertEqual(view['a'], '1') |
| | | self.assertEqual(view['attr'], None) |
| | | self.assertEqual(view['route_name'], 'name') |
| | | self.assertEqual(view['view'], DummyHandler) |
| | | |
| | | def test_add_handler_with_multiple_action(self): |
| | | config = self._makeOne(autocommit=True) |
| | | class DummyHandler(object): |
| | | def index(self): pass |
| | | def create(self): pass |
| | | create.__exposed__ = [{'name': 'index'}] |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | config.add_handler('name', '/abc', DummyHandler, action='index') |
| | | self.assertEqual(len(views), 2) |
| | | view = views[0] |
| | | self.assertEqual(view['attr'], 'create') |
| | | self.assertEqual(view['route_name'], 'name') |
| | | self.assertEqual(view['view'], DummyHandler) |
| | | view = views[1] |
| | | self.assertEqual(view['attr'], 'index') |
| | | |
| | | def test_add_handler_string(self): |
| | | import pyramid |
| | | views = [] |
| | | config = self._makeOne(autocommit=True) |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | config.add_handler('name', '/abc', 'pyramid') |
| | | self.assertEqual(len(views), 1) |
| | | view = views[0] |
| | | self.assertEqual(view['view'], pyramid) |
| | | |
| | | def test_add_handler_pattern_None_no_previous_route(self): |
| | | from pyramid.exceptions import ConfigurationError |
| | | config = self._makeOne() |
| | | self.assertRaises(ConfigurationError, config.add_handler, |
| | | 'name', None, 'pyramid') |
| | | |
| | | def test_add_handler_pattern_None_with_previous_route(self): |
| | | import pyramid |
| | | config = self._makeOne(autocommit=True) |
| | | config.add_route('name', ':def') |
| | | views = [] |
| | | def dummy_add_view(**kw): |
| | | views.append(kw) |
| | | config.add_view = dummy_add_view |
| | | config.add_route = None # shouldn't be called |
| | | config.add_handler('name', None, 'pyramid') |
| | | self.assertEqual(len(views), 1) |
| | | view = views[0] |
| | | self.assertEqual(view['view'], pyramid) |
| | | |
| | | |
| | | def _assertRoute(self, config, name, path, num_predicates=0): |
| | | from pyramid.interfaces import IRoutesMapper |
| | | mapper = config.registry.getUtility(IRoutesMapper) |
| | |
| | | else: # pragma: no cover |
| | | raise AssertionError |
| | | |
| | | def test_conflict_add_handler(self): |
| | | class AHandler(object): |
| | | def aview(self): pass |
| | | from zope.configuration.config import ConfigurationConflictError |
| | | config = self._makeOne() |
| | | config.add_handler('h1', '/h1', handler=AHandler) |
| | | config.add_handler('h1', '/h1', handler=AHandler) |
| | | try: |
| | | config.commit() |
| | | except ConfigurationConflictError, why: |
| | | c1, c2, c3, c4 = self._conflictFunctions(why) |
| | | self.assertEqual(c1, 'test_conflict_add_handler') |
| | | self.assertEqual(c2, 'test_conflict_add_handler') |
| | | self.assertEqual(c3, 'test_conflict_add_handler') |
| | | self.assertEqual(c3, 'test_conflict_add_handler') |
| | | else: # pragma: no cover |
| | | raise AssertionError |
| | | |
| | | def test_scan_conflict(self): |
| | | from zope.configuration.config import ConfigurationConflictError |
| | | from pyramid.tests import selfscanapp |
| | |
| | | for conflict in conflicts: |
| | | for confinst in conflict: |
| | | yield confinst[2] |
| | | |
| | | def test___getattr__missing_when_directives_exist(self): |
| | | config = self._makeOne() |
| | | directives = {} |
| | | config.registry._directives = directives |
| | | self.assertRaises(AttributeError, config.__getattr__, 'wontexist') |
| | | |
| | | def test___getattr__missing_when_directives_dont_exist(self): |
| | | config = self._makeOne() |
| | | self.assertRaises(AttributeError, config.__getattr__, 'wontexist') |
| | | |
| | | def test___getattr__matches(self): |
| | | config = self._makeOne() |
| | | def foo(config): pass |
| | | directives = {'foo':foo} |
| | | config.registry._directives = directives |
| | | foo_meth = config.foo |
| | | self.failUnless(foo_meth.im_func.__docobj__ is foo) |
| | | |
| | | class TestConfigurator_add_directive(unittest.TestCase): |
| | | |
| | |
| | | pass |
| | | self.assertEqual(self._callFUT(ISubException), True) |
| | | |
| | | class TestActionPredicate(unittest.TestCase): |
| | | def _getTargetClass(self): |
| | | from pyramid.config import ActionPredicate |
| | | return ActionPredicate |
| | | |
| | | def _makeOne(self, action='myaction'): |
| | | return self._getTargetClass()(action) |
| | | |
| | | def test_bad_action_regex_string(self): |
| | | from pyramid.exceptions import ConfigurationError |
| | | cls = self._getTargetClass() |
| | | self.assertRaises(ConfigurationError, cls, '[a-z') |
| | | |
| | | def test_bad_action_regex_None(self): |
| | | from pyramid.exceptions import ConfigurationError |
| | | cls = self._getTargetClass() |
| | | self.assertRaises(ConfigurationError, cls, None) |
| | | |
| | | def test___call__no_matchdict(self): |
| | | pred = self._makeOne() |
| | | request = DummyRequest() |
| | | self.assertEqual(pred(None, request), False) |
| | | |
| | | def test___call__no_action_in_matchdict(self): |
| | | pred = self._makeOne() |
| | | request = DummyRequest() |
| | | request.matchdict = {} |
| | | self.assertEqual(pred(None, request), False) |
| | | |
| | | def test___call__action_does_not_match(self): |
| | | pred = self._makeOne() |
| | | request = DummyRequest() |
| | | request.matchdict = {'action':'notmyaction'} |
| | | self.assertEqual(pred(None, request), False) |
| | | |
| | | def test___call__action_matches(self): |
| | | pred = self._makeOne() |
| | | request = DummyRequest() |
| | | request.matchdict = {'action':'myaction'} |
| | | self.assertEqual(pred(None, request), True) |
| | | |
| | | def test___hash__(self): |
| | | pred1 = self._makeOne() |
| | | pred2 = self._makeOne() |
| | | pred3 = self._makeOne(action='notthesame') |
| | | self.assertEqual(hash(pred1), hash(pred2)) |
| | | self.assertNotEqual(hash(pred1), hash(pred3)) |
| | | self.assertNotEqual(hash(pred2), hash(pred3)) |
| | | |
| | | |
| | | |
| | | class DummyRequest: |
| | | subpath = () |
| | | matchdict = None |
| | |
| | | |
| | | def dummyfactory(request): |
| | | """ """ |
| | | |
| | | class DummyHandler(object): # pragma: no cover |
| | | def __init__(self, request): |
| | | self.request = request |
| | | |
| | | def action1(self): |
| | | return 'response 1' |
| | | |
| | | def action2(self): |
| | | return 'response 2' |
| | | |
| | | def dummy_include(config): |
| | | config.action('discrim', None, config.package) |
| | |
| | | result = self._callFUT(context, request) |
| | | self.assertEqual(result, 'abc') |
| | | |
| | | class Test_action(unittest.TestCase): |
| | | def _makeOne(self, **kw): |
| | | from pyramid.view import action |
| | | return action(**kw) |
| | | |
| | | def test_call_no_previous__exposed__(self): |
| | | inst = self._makeOne(a=1, b=2) |
| | | def wrapped(): |
| | | """ """ |
| | | result = inst(wrapped) |
| | | self.failUnless(result is wrapped) |
| | | self.assertEqual(result.__exposed__, [{'a':1, 'b':2}]) |
| | | |
| | | def test_call_with_previous__exposed__(self): |
| | | inst = self._makeOne(a=1, b=2) |
| | | def wrapped(): |
| | | """ """ |
| | | wrapped.__exposed__ = [None] |
| | | result = inst(wrapped) |
| | | self.failUnless(result is wrapped) |
| | | self.assertEqual(result.__exposed__, [None, {'a':1, 'b':2}]) |
| | | |
| | | class ExceptionResponse(Exception): |
| | | status = '404 Not Found' |
| | | app_iter = ['Not Found'] |
| | |
| | | context = self.config._ctx |
| | | self.assertRaises(ConfigurationError, self._callFUT, context, 'name') |
| | | |
| | | class TestHandlerDirective(unittest.TestCase): |
| | | def setUp(self): |
| | | self.config = testing.setUp(autocommit=False) |
| | | self.config._ctx = self.config._make_context() |
| | | |
| | | def tearDown(self): |
| | | testing.tearDown() |
| | | |
| | | def _callFUT(self, *arg, **kw): |
| | | from pyramid.zcml import handler |
| | | return handler(*arg, **kw) |
| | | |
| | | def _assertRoute(self, name, pattern, num_predicates=0): |
| | | from pyramid.interfaces import IRoutesMapper |
| | | reg = self.config.registry |
| | | mapper = reg.getUtility(IRoutesMapper) |
| | | routes = mapper.get_routes() |
| | | route = routes[0] |
| | | self.assertEqual(len(routes), 1) |
| | | self.assertEqual(route.name, name) |
| | | self.assertEqual(route.pattern, pattern) |
| | | self.assertEqual(len(routes[0].predicates), num_predicates) |
| | | return route |
| | | |
| | | def test_it(self): |
| | | from pyramid.view import action |
| | | from zope.interface import Interface |
| | | from pyramid.interfaces import IView |
| | | from pyramid.interfaces import IViewClassifier |
| | | from pyramid.interfaces import IRouteRequest |
| | | reg = self.config.registry |
| | | context = self.config._ctx |
| | | class Handler(object): # pragma: no cover |
| | | def __init__(self, request): |
| | | self.request = request |
| | | action(renderer='json') |
| | | def one(self): |
| | | return 'OK' |
| | | action(renderer='json') |
| | | def two(self): |
| | | return 'OK' |
| | | self._callFUT(context, 'name', '/:action', Handler) |
| | | actions = extract_actions(context.actions) |
| | | self.assertEqual(len(actions), 3) |
| | | |
| | | route_action = actions[0] |
| | | route_discriminator = route_action['discriminator'] |
| | | self.assertEqual(route_discriminator, |
| | | ('route', 'name', False, None, None, None, None,None)) |
| | | self._assertRoute('name', '/:action') |
| | | |
| | | view_action = actions[1] |
| | | request_type = reg.getUtility(IRouteRequest, 'name') |
| | | view_discriminator = view_action['discriminator'] |
| | | discrim = ('view', None, '', None, IView, None, None, None, 'name', |
| | | 'one', False, None, None, None) |
| | | self.assertEqual(view_discriminator[:14], discrim) |
| | | view_action['callable'](*view_action['args'], **view_action['kw']) |
| | | |
| | | view_action = actions[2] |
| | | request_type = reg.getUtility(IRouteRequest, 'name') |
| | | view_discriminator = view_action['discriminator'] |
| | | discrim = ('view', None, '', None, IView, None, None, None, 'name', |
| | | 'two', False, None, None, None) |
| | | self.assertEqual(view_discriminator[:14], discrim) |
| | | view_action['callable'](*view_action['args'], **view_action['kw']) |
| | | |
| | | wrapped = reg.adapters.lookup( |
| | | (IViewClassifier, request_type, Interface), IView, name='') |
| | | self.failUnless(wrapped) |
| | | |
| | | def test_pattern_is_None(self): |
| | | from pyramid.exceptions import ConfigurationError |
| | | |
| | | context = self.config._ctx |
| | | class Handler(object): |
| | | pass |
| | | self.assertRaises(ConfigurationError, self._callFUT, |
| | | context, 'name', None, Handler) |
| | | |
| | | class TestStaticDirective(unittest.TestCase): |
| | | def setUp(self): |
| | | self.config = testing.setUp(autocommit=False) |
| | |
| | | """ |
| | | |
| | | |
| | | class action(object): |
| | | def __init__(self, **kw): |
| | | self.kw = kw |
| | | |
| | | def __call__(self, wrapped): |
| | | if hasattr(wrapped, '__exposed__'): |
| | | wrapped.__exposed__.append(self.kw) |
| | | else: |
| | | wrapped.__exposed__ = [self.kw] |
| | | return wrapped |
| | | |
| | |
| | | traverse=traverse, |
| | | ) |
| | | |
| | | class IHandlerDirective(IRouteLikeDirective): |
| | | route_name = TextLine(title=u'route_name', required=True) |
| | | handler = GlobalObject(title=u'handler', required=True) |
| | | action = TextLine(title=u"action", required=False) |
| | | |
| | | def handler(_context, |
| | | route_name, |
| | | pattern, |
| | | handler, |
| | | action=None, |
| | | view=None, |
| | | view_for=None, |
| | | permission=None, |
| | | factory=None, |
| | | for_=None, |
| | | header=None, |
| | | xhr=False, |
| | | accept=None, |
| | | path_info=None, |
| | | request_method=None, |
| | | request_param=None, |
| | | custom_predicates=(), |
| | | view_permission=None, |
| | | view_attr=None, |
| | | renderer=None, |
| | | view_renderer=None, |
| | | view_context=None, |
| | | traverse=None, |
| | | use_global_views=False): |
| | | """ Handle ``handler`` ZCML directives |
| | | """ |
| | | # the strange ordering of the request kw args above is for b/w |
| | | # compatibility purposes. |
| | | |
| | | # these are route predicates; if they do not match, the next route |
| | | # in the routelist will be tried |
| | | if view_context is None: |
| | | view_context = view_for or for_ |
| | | |
| | | view_permission = view_permission or permission |
| | | view_renderer = view_renderer or renderer |
| | | |
| | | if pattern is None: |
| | | raise ConfigurationError('handler directive must include a "pattern"') |
| | | |
| | | config = Configurator.with_context(_context) |
| | | config.add_handler( |
| | | route_name, |
| | | pattern, |
| | | handler, |
| | | action=action, |
| | | factory=factory, |
| | | header=header, |
| | | xhr=xhr, |
| | | accept=accept, |
| | | path_info=path_info, |
| | | request_method=request_method, |
| | | request_param=request_param, |
| | | custom_predicates=custom_predicates, |
| | | view=view, |
| | | view_context=view_context, |
| | | view_permission=view_permission, |
| | | view_renderer=view_renderer, |
| | | view_attr=view_attr, |
| | | use_global_views=use_global_views, |
| | | traverse=traverse, |
| | | ) |
| | | |
| | | class ISystemViewDirective(Interface): |
| | | view = GlobalObject( |
| | | title=u"", |