Merge branch 'feature.eventonly'
| | |
| | | values in parameterized ``.ini`` file, e.g. ``pshell etc/development.ini |
| | | http_port=8080``. See https://github.com/Pylons/pyramid/pull/714 |
| | | |
| | | - A somewhat advanced and obscure feature of Pyramid event handlers is their |
| | | ability to handle "multi-interface" notifications. These notifications have |
| | | traditionally presented multiple objects to the subscriber callable. For |
| | | instance, if an event was sent by code like this:: |
| | | |
| | | registry.notify(event, context) |
| | | |
| | | In the past, in order to catch such an event, you were obligated to write and |
| | | register an event subscriber that mentioned both the event and the context in |
| | | its argument list:: |
| | | |
| | | @subscriber([SomeEvent, SomeContextType]) |
| | | def asubscriber(event, context): |
| | | pass |
| | | |
| | | In many subscriber callables registered this way, it was common for the logic |
| | | in the subscriber callable to completely ignore the second and following |
| | | arguments (e.g. ``context`` in the above example might be ignored), because |
| | | they usually existed as attributes of the event anyway. You could usually |
| | | get the same value by doing ``event.context`` or similar. |
| | | |
| | | The fact that you needed to put an extra argument which you usually ignored |
| | | in the subscriber callable body was only a minor annoyance until we added |
| | | "subscriber predicates", used to narrow the set of circumstances under which |
| | | a subscriber will be executed, in a prior 1.4 alpha release. Once those were |
| | | added, the annoyance was escalated, because subscriber predicates needed to |
| | | accept the same argument list and arity as the subscriber callables that they |
| | | were configured against. So, for example, if you had these two subscriber |
| | | registrations in your code:: |
| | | |
| | | @subscriber([SomeEvent, SomeContextType]) |
| | | def asubscriber(event, context): |
| | | pass |
| | | |
| | | @subscriber(SomeOtherEvent) |
| | | def asubscriber(event): |
| | | pass |
| | | |
| | | And you wanted to use a subscriber predicate:: |
| | | |
| | | @subscriber([SomeEvent, SomeContextType], mypredicate=True) |
| | | def asubscriber1(event, context): |
| | | pass |
| | | |
| | | @subscriber(SomeOtherEvent, mypredicate=True) |
| | | def asubscriber2(event): |
| | | pass |
| | | |
| | | If an existing ``mypredicate`` subscriber predicate had been written in such |
| | | a way that it accepted only one argument in its ``__call__``, you could not |
| | | use it against a subscription which named more than one interface in its |
| | | subscriber interface list. Similarly, if you had written a subscriber |
| | | predicate that accepted two arguments, you couldn't use it against a |
| | | registration that named only a single interface type. |
| | | |
| | | For example, if you created this predicate:: |
| | | |
| | | class MyPredicate(object): |
| | | # portions elided... |
| | | def __call__(self, event): |
| | | return self.val == event.context.foo |
| | | |
| | | It would not work against a multi-interface-registered subscription, so in |
| | | the above example, when you attempted to use it against ``asubscriber1``, it |
| | | would fail at runtime with a TypeError, claiming something was attempting to |
| | | call it with too many arguments. |
| | | |
| | | To hack around this limitation, you were obligated to design the |
| | | ``mypredicate`` predicate to expect to receive in its ``__call__`` either a |
| | | single ``event`` argument (a SomeOtherEvent object) *or* a pair of arguments |
| | | (a SomeEvent object and a SomeContextType object), presumably by doing |
| | | something like this:: |
| | | |
| | | class MyPredicate(object): |
| | | # portions elided... |
| | | def __call__(self, event, context=None): |
| | | return self.val == event.context.foo |
| | | |
| | | This was confusing and bad. |
| | | |
| | | In order to allow people to ignore unused arguments to subscriber callables |
| | | and to normalize the relationship between event subscribers and subscriber |
| | | predicates, we now allow both subscribers and subscriber predicates to accept |
| | | only a single ``event`` argument even if they've been subscribed for |
| | | notifications that involve multiple interfaces. Subscribers and subscriber |
| | | predicates that accept only one argument will receive the first object passed |
| | | to ``notify``; this is typically (but not always) the event object. The |
| | | other objects involved in the subscription lookup will be discarded. You can |
| | | now write an event subscriber that accepts only ``event`` even if it |
| | | subscribes to multiple interfaces:: |
| | | |
| | | @subscriber([SomeEvent, SomeContextType]) |
| | | def asubscriber(event): |
| | | # this will work! |
| | | |
| | | This prevents you from needing to match the subscriber callable parameters to |
| | | the subscription type unnecessarily, especially when you don't make use of |
| | | any argument in your subscribers except for the event object itself. |
| | | |
| | | Note, however, that if the event object is not the first |
| | | object in the call to ``notify``, you'll run into trouble. For example, if |
| | | notify is called with the context argument first:: |
| | | |
| | | registry.notify(context, event) |
| | | |
| | | You won't be able to take advantage of the event-only feature. It will |
| | | "work", but the object received by your event handler won't be the event |
| | | object, it will be the context object, which won't be very useful:: |
| | | |
| | | @subscriber([SomeContextType, SomeEvent]) |
| | | def asubscriber(event): |
| | | # bzzt! you'll be getting the context here as ``event``, and it'll |
| | | # be useless |
| | | |
| | | Existing multiple-argument subscribers continue to work without issue, so you |
| | | should continue use those if your system notifies using multiple interfaces |
| | | and the first interface is not the event interface. For example:: |
| | | |
| | | @subscriber([SomeContextType, SomeEvent]) |
| | | def asubscriber(context, event): |
| | | # this will still work! |
| | | |
| | | The event-only feature makes it possible to use a subscriber predicate that |
| | | accepts only a request argument within both multiple-interface subscriber |
| | | registrations and single-interface subscriber registrations. You needn't |
| | | make slightly different variations of predicates depending on the |
| | | subscription type arguments. Instead, just write all your subscriber |
| | | predicates so they only accept ``event`` in their ``__call__`` and they'll be |
| | | useful across all registrations for subscriptions that use an event as their |
| | | first argument, even ones which accept more than just ``event``. |
| | | |
| | | However, the same caveat applies to predicates as to subscriber callables: if |
| | | you're subscribing to a multi-interface event, and the first interface is not |
| | | the event interface, the predicate won't work properly. In such a case, |
| | | you'll need to match the predicate ``__call__`` argument ordering and |
| | | composition to the ordering of the interfaces. For example, if the |
| | | registration for the subscription uses ``[SomeContext, SomeEvent]``, you'll |
| | | need to reflect that in the ordering of the parameters of the predicate's |
| | | ``__call__`` method:: |
| | | |
| | | def __call__(self, context, event): |
| | | return event.request.path.startswith(self.val) |
| | | |
| | | tl;dr: 1) When using multi-interface subscriptions, always use the event type |
| | | as the first subscription registration argument and 2) When 1 is true, use |
| | | only ``event`` in your subscriber and subscriber predicate parameter lists, |
| | | no matter how many interfaces the subscriber is notified with. This |
| | | combination will result in the maximum amount of reusability of subscriber |
| | | predicates and the least amount of thought on your part. Drink responsibly. |
| | | |
| | | Bug Fixes |
| | | --------- |
| | | |
| | |
| | | |
| | | from pyramid.config.util import ( |
| | | action_method, |
| | | takes_one_arg, |
| | | ) |
| | | |
| | | |
| | |
| | | def register(): |
| | | predlist = self.get_predlist('subscriber') |
| | | order, preds, phash = predlist.make(self, **predicates) |
| | | intr.update({'phash':phash, 'order':order, 'predicates':preds}) |
| | | derived_subscriber = self._derive_subscriber(subscriber, preds) |
| | | |
| | | derived_predicates = [ self._derive_predicate(p) for p in preds ] |
| | | derived_subscriber = self._derive_subscriber( |
| | | subscriber, |
| | | derived_predicates, |
| | | ) |
| | | |
| | | intr.update( |
| | | {'phash':phash, |
| | | 'order':order, |
| | | 'predicates':preds, |
| | | 'derived_predicates':derived_predicates, |
| | | 'derived_subscriber':derived_subscriber, |
| | | } |
| | | ) |
| | | |
| | | self.registry.registerHandler(derived_subscriber, iface) |
| | | |
| | | intr = self.introspectable( |
| | |
| | | self.action(None, register, introspectables=(intr,)) |
| | | return subscriber |
| | | |
| | | def _derive_predicate(self, predicate): |
| | | derived_predicate = predicate |
| | | |
| | | if eventonly(predicate): |
| | | def derived_predicate(*arg): |
| | | return predicate(arg[0]) |
| | | # seems pointless to try to fix __doc__, __module__, etc as |
| | | # predicate will invariably be an instance |
| | | |
| | | return derived_predicate |
| | | |
| | | def _derive_subscriber(self, subscriber, predicates): |
| | | derived_subscriber = subscriber |
| | | |
| | | if eventonly(subscriber): |
| | | def derived_subscriber(*arg): |
| | | return subscriber(arg[0]) |
| | | if hasattr(subscriber, '__name__'): |
| | | update_wrapper(derived_subscriber, subscriber) |
| | | |
| | | if not predicates: |
| | | return subscriber |
| | | return derived_subscriber |
| | | |
| | | def subscriber_wrapper(*arg): |
| | | # We need to accept *arg and pass it along because zope |
| | | # subscribers are designed poorly. Notification will always call |
| | | # an associated subscriber with all of the objects involved in |
| | | # the subscription lookup, despite the fact that the event sender |
| | | # always has the option to attach those objects to the event |
| | | # object itself (and usually does). It would be much saner if the |
| | | # registry just used extra args passed to notify to do the lookup |
| | | # but only called event subscribers with the actual event object, |
| | | # or if we had been smart enough early on to always wrap |
| | | # subscribers in something that threw away the extra args, but |
| | | # c'est la vie. |
| | | # We need to accept *arg and pass it along because zope subscribers |
| | | # are designed awkwardly. Notification via |
| | | # registry.adapter.subscribers will always call an associated |
| | | # subscriber with all of the objects involved in the subscription |
| | | # lookup, despite the fact that the event sender always has the |
| | | # option to attach those objects to the event object itself, and |
| | | # almost always does. |
| | | # |
| | | # The "eventonly" jazz sprinkled in this function and related |
| | | # functions allows users to define subscribers and predicates which |
| | | # accept only an event argument without needing to accept the rest |
| | | # of the adaptation arguments. Had I been smart enough early on to |
| | | # use .subscriptions to find the subscriber functions in order to |
| | | # call them manually with a single "event" argument instead of |
| | | # relying on .subscribers to both find and call them implicitly |
| | | # with all args, the eventonly hack would not have been required. |
| | | # At this point, though, using .subscriptions and manual execution |
| | | # is not possible without badly breaking backwards compatibility. |
| | | if all((predicate(*arg) for predicate in predicates)): |
| | | return subscriber(*arg) |
| | | return derived_subscriber(*arg) |
| | | |
| | | if hasattr(subscriber, '__name__'): |
| | | update_wrapper(subscriber_wrapper, subscriber) |
| | | |
| | | return subscriber_wrapper |
| | | |
| | | @action_method |
| | |
| | | if resource_iface is None: |
| | | resource_iface = Interface |
| | | self.registry.registerAdapter( |
| | | adapter, |
| | | adapter, |
| | | (resource_iface, Interface), |
| | | IResourceURL, |
| | | ) |
| | |
| | | intr['resource_iface'] = resource_iface |
| | | self.action(discriminator, register, introspectables=(intr,)) |
| | | |
| | | def eventonly(callee): |
| | | return takes_one_arg(callee, argname='event') |
| | |
| | | from hashlib import md5 |
| | | import inspect |
| | | |
| | | from pyramid.compat import ( |
| | | bytes_, |
| | | is_nonstr_iter, |
| | | ) |
| | | |
| | | from pyramid.compat import im_func |
| | | from pyramid.exceptions import ConfigurationError |
| | | from pyramid.registry import predvalseq |
| | | |
| | |
| | | order = (MAX_ORDER - score) / (len(preds) + 1) |
| | | return order, preds, phash.hexdigest() |
| | | |
| | | def takes_one_arg(callee, attr=None, argname=None): |
| | | ismethod = False |
| | | if attr is None: |
| | | attr = '__call__' |
| | | if inspect.isroutine(callee): |
| | | fn = callee |
| | | elif inspect.isclass(callee): |
| | | try: |
| | | fn = callee.__init__ |
| | | except AttributeError: |
| | | return False |
| | | ismethod = hasattr(fn, '__call__') |
| | | else: |
| | | try: |
| | | fn = getattr(callee, attr) |
| | | except AttributeError: |
| | | return False |
| | | |
| | | try: |
| | | argspec = inspect.getargspec(fn) |
| | | except TypeError: |
| | | return False |
| | | |
| | | args = argspec[0] |
| | | |
| | | if hasattr(fn, im_func) or ismethod: |
| | | # it's an instance method (or unbound method on py2) |
| | | if not args: |
| | | return False |
| | | args = args[1:] |
| | | |
| | | if not args: |
| | | return False |
| | | |
| | | if len(args) == 1: |
| | | return True |
| | | |
| | | if argname: |
| | | |
| | | defaults = argspec[3] |
| | | if defaults is None: |
| | | defaults = () |
| | | |
| | | if args[0] == argname: |
| | | if len(args) - len(defaults) == 1: |
| | | return True |
| | | |
| | | return False |
| | |
| | | from pyramid.config.util import ( |
| | | DEFAULT_PHASH, |
| | | MAX_ORDER, |
| | | takes_one_arg, |
| | | ) |
| | | |
| | | urljoin = urlparse.urljoin |
| | |
| | | return _attr_view |
| | | |
| | | def requestonly(view, attr=None): |
| | | ismethod = False |
| | | if attr is None: |
| | | attr = '__call__' |
| | | if inspect.isroutine(view): |
| | | fn = view |
| | | elif inspect.isclass(view): |
| | | try: |
| | | fn = view.__init__ |
| | | except AttributeError: |
| | | return False |
| | | ismethod = hasattr(fn, '__call__') |
| | | else: |
| | | try: |
| | | fn = getattr(view, attr) |
| | | except AttributeError: |
| | | return False |
| | | |
| | | try: |
| | | argspec = inspect.getargspec(fn) |
| | | except TypeError: |
| | | return False |
| | | |
| | | args = argspec[0] |
| | | |
| | | if hasattr(fn, im_func) or ismethod: |
| | | # it's an instance method (or unbound method on py2) |
| | | if not args: |
| | | return False |
| | | args = args[1:] |
| | | if not args: |
| | | return False |
| | | |
| | | if len(args) == 1: |
| | | return True |
| | | |
| | | defaults = argspec[3] |
| | | if defaults is None: |
| | | defaults = () |
| | | |
| | | if args[0] == 'request': |
| | | if len(args) - len(defaults) == 1: |
| | | return True |
| | | |
| | | return False |
| | | return takes_one_arg(view, attr=attr, argname='request') |
| | | |
| | | @implementer(IMultiView) |
| | | class MultiView(object): |
| | |
| | | self.assertEqual(intr['adapter'], DummyResourceURL) |
| | | self.assertEqual(intr['resource_iface'], DummyIface) |
| | | |
| | | class Test_eventonly(unittest.TestCase): |
| | | def _callFUT(self, callee): |
| | | from pyramid.config.adapters import eventonly |
| | | return eventonly(callee) |
| | | |
| | | def test_defaults(self): |
| | | def acallable(event, a=1, b=2): pass |
| | | self.assertTrue(self._callFUT(acallable)) |
| | | |
| | | class DummyTraverser(object): |
| | | def __init__(self, root): |
| | | self.root = root |
| | |
| | | from pyramid.exceptions import ConfigurationError |
| | | self.assertRaises(ConfigurationError, self._callFUT, unknown=1) |
| | | |
| | | class Test_takes_one_arg(unittest.TestCase): |
| | | def _callFUT(self, view, attr=None, argname=None): |
| | | from pyramid.config.util import takes_one_arg |
| | | return takes_one_arg(view, attr=attr, argname=argname) |
| | | |
| | | def test_requestonly_newstyle_class_no_init(self): |
| | | class foo(object): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_requestonly_newstyle_class_init_toomanyargs(self): |
| | | class foo(object): |
| | | def __init__(self, context, request): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_requestonly_newstyle_class_init_onearg_named_request(self): |
| | | class foo(object): |
| | | def __init__(self, request): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_onearg_named_somethingelse(self): |
| | | class foo(object): |
| | | def __init__(self, req): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_defaultargs_firstname_not_request(self): |
| | | class foo(object): |
| | | def __init__(self, context, request=None): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_defaultargs_firstname_request(self): |
| | | class foo(object): |
| | | def __init__(self, request, foo=1, bar=2): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo, argname='request')) |
| | | |
| | | def test_newstyle_class_init_firstname_request_with_secondname(self): |
| | | class foo(object): |
| | | def __init__(self, request, two): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_noargs(self): |
| | | class foo(object): |
| | | def __init__(): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_no_init(self): |
| | | class foo: |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_toomanyargs(self): |
| | | class foo: |
| | | def __init__(self, context, request): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_onearg_named_request(self): |
| | | class foo: |
| | | def __init__(self, request): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_onearg_named_somethingelse(self): |
| | | class foo: |
| | | def __init__(self, req): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_defaultargs_firstname_not_request(self): |
| | | class foo: |
| | | def __init__(self, context, request=None): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_defaultargs_firstname_request(self): |
| | | class foo: |
| | | def __init__(self, request, foo=1, bar=2): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo, argname='request'), True) |
| | | |
| | | def test_oldstyle_class_init_noargs(self): |
| | | class foo: |
| | | def __init__(): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_function_toomanyargs(self): |
| | | def foo(context, request): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_function_with_attr_false(self): |
| | | def bar(context, request): |
| | | """ """ |
| | | def foo(context, request): |
| | | """ """ |
| | | foo.bar = bar |
| | | self.assertFalse(self._callFUT(foo, 'bar')) |
| | | |
| | | def test_function_with_attr_true(self): |
| | | def bar(context, request): |
| | | """ """ |
| | | def foo(request): |
| | | """ """ |
| | | foo.bar = bar |
| | | self.assertTrue(self._callFUT(foo, 'bar')) |
| | | |
| | | def test_function_onearg_named_request(self): |
| | | def foo(request): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_function_onearg_named_somethingelse(self): |
| | | def foo(req): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_function_defaultargs_firstname_not_request(self): |
| | | def foo(context, request=None): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_function_defaultargs_firstname_request(self): |
| | | def foo(request, foo=1, bar=2): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo, argname='request')) |
| | | |
| | | def test_function_noargs(self): |
| | | def foo(): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_instance_toomanyargs(self): |
| | | class Foo: |
| | | def __call__(self, context, request): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_instance_defaultargs_onearg_named_request(self): |
| | | class Foo: |
| | | def __call__(self, request): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_instance_defaultargs_onearg_named_somethingelse(self): |
| | | class Foo: |
| | | def __call__(self, req): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_instance_defaultargs_firstname_not_request(self): |
| | | class Foo: |
| | | def __call__(self, context, request=None): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_instance_defaultargs_firstname_request(self): |
| | | class Foo: |
| | | def __call__(self, request, foo=1, bar=2): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertTrue(self._callFUT(foo, argname='request'), True) |
| | | |
| | | def test_instance_nocall(self): |
| | | class Foo: pass |
| | | foo = Foo() |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_method_onearg_named_request(self): |
| | | class Foo: |
| | | def method(self, request): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertTrue(self._callFUT(foo.method)) |
| | | |
| | | |
| | | class DummyCustomPredicate(object): |
| | | def __init__(self): |
| | |
| | | from pyramid.tests import test_config |
| | | self.assertEqual(result, test_config) |
| | | |
| | | |
| | | class Test_requestonly(unittest.TestCase): |
| | | def _callFUT(self, view, attr=None): |
| | | from pyramid.config.views import requestonly |
| | | return requestonly(view, attr) |
| | | return requestonly(view, attr=attr) |
| | | |
| | | def test_requestonly_newstyle_class_no_init(self): |
| | | class foo(object): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | def test_defaults(self): |
| | | def aview(request, a=1, b=2): pass |
| | | self.assertTrue(self._callFUT(aview)) |
| | | |
| | | def test_requestonly_newstyle_class_init_toomanyargs(self): |
| | | class foo(object): |
| | | def __init__(self, context, request): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_requestonly_newstyle_class_init_onearg_named_request(self): |
| | | class foo(object): |
| | | def __init__(self, request): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_onearg_named_somethingelse(self): |
| | | class foo(object): |
| | | def __init__(self, req): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_defaultargs_firstname_not_request(self): |
| | | class foo(object): |
| | | def __init__(self, context, request=None): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_defaultargs_firstname_request(self): |
| | | class foo(object): |
| | | def __init__(self, request, foo=1, bar=2): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_firstname_request_with_secondname(self): |
| | | class foo(object): |
| | | def __init__(self, request, two): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_newstyle_class_init_noargs(self): |
| | | class foo(object): |
| | | def __init__(): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_no_init(self): |
| | | class foo: |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_toomanyargs(self): |
| | | class foo: |
| | | def __init__(self, context, request): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_onearg_named_request(self): |
| | | class foo: |
| | | def __init__(self, request): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_onearg_named_somethingelse(self): |
| | | class foo: |
| | | def __init__(self, req): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_defaultargs_firstname_not_request(self): |
| | | class foo: |
| | | def __init__(self, context, request=None): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_oldstyle_class_init_defaultargs_firstname_request(self): |
| | | class foo: |
| | | def __init__(self, request, foo=1, bar=2): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo), True) |
| | | |
| | | def test_oldstyle_class_init_noargs(self): |
| | | class foo: |
| | | def __init__(): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_function_toomanyargs(self): |
| | | def foo(context, request): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_function_with_attr_false(self): |
| | | def bar(context, request): |
| | | """ """ |
| | | def foo(context, request): |
| | | """ """ |
| | | foo.bar = bar |
| | | self.assertFalse(self._callFUT(foo, 'bar')) |
| | | |
| | | def test_function_with_attr_true(self): |
| | | def bar(context, request): |
| | | """ """ |
| | | def foo(request): |
| | | """ """ |
| | | foo.bar = bar |
| | | self.assertTrue(self._callFUT(foo, 'bar')) |
| | | |
| | | def test_function_onearg_named_request(self): |
| | | def foo(request): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_function_onearg_named_somethingelse(self): |
| | | def foo(req): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_function_defaultargs_firstname_not_request(self): |
| | | def foo(context, request=None): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_function_defaultargs_firstname_request(self): |
| | | def foo(request, foo=1, bar=2): |
| | | """ """ |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_function_noargs(self): |
| | | def foo(): |
| | | """ """ |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_instance_toomanyargs(self): |
| | | class Foo: |
| | | def __call__(self, context, request): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_instance_defaultargs_onearg_named_request(self): |
| | | class Foo: |
| | | def __call__(self, request): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_instance_defaultargs_onearg_named_somethingelse(self): |
| | | class Foo: |
| | | def __call__(self, req): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertTrue(self._callFUT(foo)) |
| | | |
| | | def test_instance_defaultargs_firstname_not_request(self): |
| | | class Foo: |
| | | def __call__(self, context, request=None): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_instance_defaultargs_firstname_request(self): |
| | | class Foo: |
| | | def __call__(self, request, foo=1, bar=2): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertTrue(self._callFUT(foo), True) |
| | | |
| | | def test_instance_nocall(self): |
| | | class Foo: pass |
| | | foo = Foo() |
| | | self.assertFalse(self._callFUT(foo)) |
| | | |
| | | def test_method_onearg_named_request(self): |
| | | class Foo: |
| | | def method(self, request): |
| | | """ """ |
| | | foo = Foo() |
| | | self.assertTrue(self._callFUT(foo.method)) |
| | | def test_otherattr(self): |
| | | class AView(object): |
| | | def __init__(self, request, a=1, b=2): pass |
| | | def bleh(self): pass |
| | | self.assertTrue(self._callFUT(AView, 'bleh')) |
| | | |
| | | class Test_isexception(unittest.TestCase): |
| | | def _callFUT(self, ob): |
| | |
| | | def test_oob_slash(self): |
| | | self.testapp.get('/%2F/test_integration.py', status=404) |
| | | |
| | | class TestEventOnlySubscribers(IntegrationBase, unittest.TestCase): |
| | | package = 'pyramid.tests.pkgs.eventonly' |
| | | |
| | | def test_sendfoo(self): |
| | | res = self.testapp.get('/sendfoo', status=200) |
| | | self.assertEqual(sorted(res.body.split()), [b'foo', b'fooyup']) |
| | | |
| | | def test_sendfoobar(self): |
| | | res = self.testapp.get('/sendfoobar', status=200) |
| | | self.assertEqual(sorted(res.body.split()), |
| | | [b'foobar', b'foobar2', b'foobaryup', b'foobaryup2']) |
| | | |
| | | class TestStaticAppUsingAbsPath(TestStaticAppBase, unittest.TestCase): |
| | | package = 'pyramid.tests.pkgs.static_abspath' |
| | | |