summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2019-09-20 00:09:29 -0500
committerMichael Merickel <michael@merickel.org>2019-10-02 10:03:07 -0500
commitba311842b667348c51fb1a479ae08a042434f1bc (patch)
treea34f4945305113a8666618e255281858ee2f825a
parentbe62391821676393b7ad5ab51655892e991c2ae0 (diff)
downloadpyramid-ba311842b667348c51fb1a479ae08a042434f1bc.tar.gz
pyramid-ba311842b667348c51fb1a479ae08a042434f1bc.tar.bz2
pyramid-ba311842b667348c51fb1a479ae08a042434f1bc.zip
define an IPredicateInfo instead of passing the full configurator to predicates
-rw-r--r--docs/api/interfaces.rst21
-rw-r--r--src/pyramid/config/predicates.py16
-rw-r--r--src/pyramid/interfaces.py85
-rw-r--r--tests/test_config/test_predicates.py6
4 files changed, 127 insertions, 1 deletions
diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst
index e542a6be0..08c67c385 100644
--- a/docs/api/interfaces.rst
+++ b/docs/api/interfaces.rst
@@ -109,3 +109,24 @@ Other Interfaces
.. autointerface:: IViewDeriverInfo
:members:
+
+ .. autointerface:: IPredicateFactory
+ :members:
+
+ .. autointerface:: IPredicateInfo
+ :members:
+
+ .. autointerface:: IPredicate
+ :members:
+
+ .. autointerface:: IRoutePredicate
+ :inherited-members:
+ :members:
+
+ .. autointerface:: ISubscriberPredicate
+ :inherited-members:
+ :members:
+
+ .. autointerface:: IViewPredicate
+ :inherited-members:
+ :members:
diff --git a/src/pyramid/config/predicates.py b/src/pyramid/config/predicates.py
index 3eb07c17d..ffdff5c21 100644
--- a/src/pyramid/config/predicates.py
+++ b/src/pyramid/config/predicates.py
@@ -98,6 +98,14 @@ class not_(object):
# over = before
+class PredicateInfo(object):
+ def __init__(self, package, registry, settings, maybe_dotted):
+ self.package = package
+ self.registry = registry
+ self.settings = settings
+ self.maybe_dotted = maybe_dotted
+
+
class PredicateList(object):
def __init__(self):
self.sorter = TopologicalSorter()
@@ -134,6 +142,12 @@ class PredicateList(object):
phash = md5()
weights = []
preds = []
+ info = PredicateInfo(
+ package=config.package,
+ registry=config.registry,
+ settings=config.get_settings(),
+ maybe_dotted=config.maybe_dotted,
+ )
for n, (name, predicate_factory) in enumerate(ordered):
vals = kw.pop(name, None)
if vals is None: # XXX should this be a sentinel other than None?
@@ -146,7 +160,7 @@ class PredicateList(object):
if isinstance(val, not_):
realval = val.value
notted = True
- pred = predicate_factory(realval, config)
+ pred = predicate_factory(realval, info)
if notted:
pred = Notted(pred)
hashes = pred.phash()
diff --git a/src/pyramid/interfaces.py b/src/pyramid/interfaces.py
index 2d8b1ac40..688293509 100644
--- a/src/pyramid/interfaces.py
+++ b/src/pyramid/interfaces.py
@@ -1440,6 +1440,91 @@ class IPredicateList(Interface):
""" Interface representing a predicate list """
+class IPredicateInfo(Interface):
+ package = Attribute(
+ 'The "current package" where the predicate '
+ 'configuration statement was found'
+ )
+ registry = Attribute(
+ 'The "current" application registry where the predicate was invoked'
+ )
+ settings = Attribute(
+ 'The deployment settings dictionary related '
+ 'to the current application'
+ )
+
+ def maybe_dotted(value):
+ """ Resolve the :term:`dotted Python name` ``dotted`` to a
+ global Python object. If ``dotted`` is not a string, return
+ it without attempting to do any name resolution. If
+ ``dotted`` is a relative dotted name (e.g. ``.foo.bar``,
+ consider it relative to the ``package``."""
+
+
+class IPredicateFactory(Interface):
+ def __call__(value, info):
+ """
+ Create a a :class:`.IPredicate` instance for a specific value.
+
+ """
+
+
+class IPredicate(Interface):
+ def text():
+ """
+ A textual description of the predicate used in the introspector.
+
+ For example, ``'content_type = application/json'`` for a
+ ``ContentTypePredicate`` with a ``value == 'application/json'``.
+
+ """
+
+ def phash():
+ """
+ A unique string for the predicate containing both the name and value.
+
+ Often implementations simply set ``phash = text``.
+
+ """
+
+
+class IRoutePredicate(IPredicate):
+ def __call__(info, request):
+ """
+ The ``info`` object is a dictionary containing two keys:
+
+ - "match" is a dictionary of parameters that becomes
+ ``request.matchdict`` if the route is selected
+ (all route predicates match).
+
+ - "route" is the :class:`.IRoute` object being matched.
+
+ Return ``True`` if the route should be selected or ``False`` otherwise.
+
+ """
+
+
+class ISubscriberPredicate(IPredicate):
+ def __call__(*args):
+ """
+ The ``args`` is usually just a single ``event`` argument sent to
+ ``registry.notify``.
+
+ Return ``True`` if the subscriber should be executed for the given
+ arguments or ``False`` otherwise.
+
+ """
+
+
+class IViewPredicate(IPredicate):
+ def __call__(context, request):
+ """
+ Return ``True`` if the view should be selected for the given
+ arguments or ``False`` otherwise.
+
+ """
+
+
class IViewDeriver(Interface):
options = Attribute(
'A list of supported options to be passed to '
diff --git a/tests/test_config/test_predicates.py b/tests/test_config/test_predicates.py
index c27b41639..f8abbbce4 100644
--- a/tests/test_config/test_predicates.py
+++ b/tests/test_config/test_predicates.py
@@ -476,5 +476,11 @@ class DummyRequest:
class DummyConfigurator(object):
+ package = 'dummy package'
+ registry = 'dummy registry'
+
+ def get_settings(self):
+ return {}
+
def maybe_dotted(self, thing):
return thing