diff options
| author | Michael Merickel <michael@merickel.org> | 2024-01-27 17:33:26 -0700 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2024-01-27 17:33:26 -0700 |
| commit | 19ae96b97ea055c2e36c8fb86819c426b37ab6af (patch) | |
| tree | 437540b467bd1a2af90409145935742537b3699e | |
| parent | 8a9d78106fd3b6d6dc44fabd205ee2c58fffef08 (diff) | |
| download | pyramid-19ae96b97ea055c2e36c8fb86819c426b37ab6af.tar.gz pyramid-19ae96b97ea055c2e36c8fb86819c426b37ab6af.tar.bz2 pyramid-19ae96b97ea055c2e36c8fb86819c426b37ab6af.zip | |
revert restriction to eventonly predicates, allow a predicate to receive all args
| -rw-r--r-- | src/pyramid/config/adapters.py | 26 | ||||
| -rw-r--r-- | src/pyramid/util.py | 5 | ||||
| -rw-r--r-- | tests/pkgs/eventonly/__init__.py | 19 | ||||
| -rw-r--r-- | tests/test_integration.py | 8 |
4 files changed, 53 insertions, 5 deletions
diff --git a/src/pyramid/config/adapters.py b/src/pyramid/config/adapters.py index 08bfff142..8a043cf56 100644 --- a/src/pyramid/config/adapters.py +++ b/src/pyramid/config/adapters.py @@ -45,13 +45,17 @@ class AdaptersConfiguratorMixin: predlist = self.get_predlist('subscriber') order, preds, phash = predlist.make(self, **predicates) - 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, } ) @@ -71,6 +75,19 @@ class AdaptersConfiguratorMixin: self.action(None, register, introspectables=(intr,)) return subscriber + def _derive_predicate(self, 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 + else: + derived_predicate = predicate + + return derived_predicate + def _derive_subscriber(self, subscriber, predicates): if eventonly(subscriber): @@ -104,7 +121,7 @@ class AdaptersConfiguratorMixin: # 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[0]) for predicate in predicates): + if all(predicate(*arg) for predicate in predicates): return derived_subscriber(*arg) if hasattr(subscriber, '__name__'): @@ -309,4 +326,7 @@ class AdaptersConfiguratorMixin: def eventonly(callee): - return takes_one_arg(callee, argname='event') + # we do not count a function as eventonly if it accepts *args + # which will open up the possibility for the function to receive + # all of the args + return takes_one_arg(callee, argname='event', allow_varargs=False) diff --git a/src/pyramid/util.py b/src/pyramid/util.py index f396712f3..c71528a49 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -652,7 +652,7 @@ def make_contextmanager(fn): return wrapper -def takes_one_arg(callee, attr=None, argname=None): +def takes_one_arg(callee, attr=None, argname=None, allow_varargs=True): ismethod = False if attr is None: attr = '__call__' @@ -679,6 +679,9 @@ def takes_one_arg(callee, attr=None, argname=None): if not args: return False + if not allow_varargs and argspec.varargs: + return False + if len(args) == 1: return True diff --git a/tests/pkgs/eventonly/__init__.py b/tests/pkgs/eventonly/__init__.py index e45a5691f..f7a9270dc 100644 --- a/tests/pkgs/eventonly/__init__.py +++ b/tests/pkgs/eventonly/__init__.py @@ -15,6 +15,19 @@ class Yup: return getattr(event.response, 'yup', False) +class YupWithAllArgs: + def __init__(self, val, config): + self.val = val + + def text(self): + return f'yup_with_extra_args = {self.val}' + + phash = text + + def __call__(self, event, *args): + return getattr(event.response, 'yup', False) + + class Foo: def __init__(self, response): self.response = response @@ -54,6 +67,11 @@ def foobaryup2(event, context): event.response.text += 'foobaryup2 ' +@subscriber([Foo, Bar], yup=True, yup_with_all_args=True) +def foobaryup3(event, context): + event.response.text += 'foobaryup3 ' + + @view_config(name='sendfoo') def sendfoo(request): response = request.response @@ -72,4 +90,5 @@ def sendfoobar(request): def includeme(config): config.add_subscriber_predicate('yup', Yup) + config.add_subscriber_predicate('yup_with_all_args', YupWithAllArgs) config.scan('tests.pkgs.eventonly') diff --git a/tests/test_integration.py b/tests/test_integration.py index 63a7088e9..7ca11e81e 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -213,7 +213,13 @@ class TestEventOnlySubscribers(IntegrationBase, unittest.TestCase): res = self.testapp.get('/sendfoobar', status=200) self.assertEqual( sorted(res.body.split()), - [b'foobar', b'foobar2', b'foobaryup', b'foobaryup2'], + [ + b'foobar', + b'foobar2', + b'foobaryup', + b'foobaryup2', + b'foobaryup3', + ], ) |
