summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉric Araujo <earaujo@caravan.coop>2020-01-07 14:33:31 -0500
committerÉric Araujo <earaujo@caravan.coop>2020-01-07 14:33:31 -0500
commit26d2d87bc2865a431b5eb30552c3eac4108b3a0c (patch)
tree2bcecba6b70e79eb8d732d8eceeb5e3ff1d46ef1
parent5702c3c3a4357a6071c9ba624a89655209548336 (diff)
downloadpyramid-26d2d87bc2865a431b5eb30552c3eac4108b3a0c.tar.gz
pyramid-26d2d87bc2865a431b5eb30552c3eac4108b3a0c.tar.bz2
pyramid-26d2d87bc2865a431b5eb30552c3eac4108b3a0c.zip
rewrite docs for custom predicates
-rw-r--r--docs/narr/hooks.rst2
-rw-r--r--docs/narr/urldispatch.rst179
-rw-r--r--docs/narr/viewconfig.rst18
-rw-r--r--docs/quick_tour.rst2
-rw-r--r--src/pyramid/config/routes.py12
-rw-r--r--src/pyramid/config/views.py12
6 files changed, 120 insertions, 105 deletions
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 4a594a8c9..fbb845447 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -1564,7 +1564,7 @@ event type.
self.val = val
def text(self):
- return 'path_startswith = %s' % (self.val,)
+ return 'request_path_startswith = %s' % (self.val,)
phash = text
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 9372163e8..6dd8b1455 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -1087,11 +1087,8 @@ A convenience context manager exists to set the route prefix for any
Custom Route Predicates
-----------------------
-Each of the predicate callables fed to the ``custom_predicates`` argument of
-:meth:`~pyramid.config.Configurator.add_route` must be a callable accepting two
-arguments. The first argument passed to a custom predicate is a dictionary
-conventionally named ``info``. The second argument is the current
-:term:`request` object.
+A predicate is a callable that accepts two arguments: a dictionary
+conventionally named ``info``, and the current :term:`request` object.
The ``info`` dictionary has a number of contained values, including ``match``
and ``route``. ``match`` is a dictionary which represents the arguments matched
@@ -1100,52 +1097,73 @@ was matched (see :class:`pyramid.interfaces.IRoute` for the API of such a route
object).
``info['match']`` is useful when predicates need access to the route match.
-For example:
+Imagine you want to define a route when a part of the URL matches some
+specific values. You could define three view configurations, each one
+with its own ``match_param`` value (see :ref:`predicate_view_args`), but
+you want to think of it as one route, and associate it with one view.
+See this code:
.. code-block:: python
:linenos:
- def any_of(segment_name, *allowed):
- def predicate(info, request):
- if info['match'][segment_name] in allowed:
- return True
- return predicate
+ class AnyOfPredicate:
+ def __init__(self, val):
+ self.segment_name = val[0]
+ self.allowed = tuple(val[0:])
+
+ def text(self):
+ args = (self.segment_name,) + self.allowed
+ return 'any_of = %s' % (args,)
+
+ phash = text
+
+ def __call__(self, info, request):
+ return info['match'][self.segment_name] in self.allowed
+
- num_one_two_or_three = any_of('num', 'one', 'two', 'three')
+ config.add_route_predicate("any_of", AnyOfPredicate)
+ config.add_route('route_to_num', '/{num}', any_of=('num', 'one', 'two', 'three'))
- config.add_route('route_to_num', '/{num}',
- custom_predicates=(num_one_two_or_three,))
-The above ``any_of`` function generates a predicate which ensures that the
+An instance of the class defined above is a predicate which ensures that the
match value named ``segment_name`` is in the set of allowable values
-represented by ``allowed``. We use this ``any_of`` function to generate a
-predicate function named ``num_one_two_or_three``, which ensures that the
-``num`` segment is one of the values ``one``, ``two``, or ``three`` , and use
-the result as a custom predicate by feeding it inside a tuple to the
-``custom_predicates`` argument to
-:meth:`~pyramid.config.Configurator.add_route`.
+represented by ``allowed``. We register this class as a *predicate
+factory* with the ``any_of`` argument name, then we can use that new
+keyword argument with :meth:`~pyramid.config.Configurator.add_route` to
+have Pyramid instantiate the class (the ``('num', 'one', 'two',
+'three')`` value is passed to the constructor as the argument ``val``)
+and use the resulting instance as a custom predicate to check if
+incoming requests match the route or not.
A custom route predicate may also *modify* the ``match`` dictionary. For
instance, a predicate might do some type conversion of values:
.. code-block:: python
- :linenos:
+ :linenos:
+
+ class IntegersPredicate:
+
+ def __init__(self, val):
+ self.segment_names = val
+
+ def text(self):
+ return 'integers = %s' % (self.segment_names,)
- def integers(*segment_names):
- def predicate(info, request):
- match = info['match']
- for segment_name in segment_names:
- try:
- match[segment_name] = int(match[segment_name])
- except (TypeError, ValueError):
- pass
- return True
- return predicate
+ phash = text
- ymd_to_int = integers('year', 'month', 'day')
+ def __call__(self, info, request):
+ match = info['match']
+ for segment_name in self.segment_names:
+ try:
+ match[segment_name] = int(match[segment_name])
+ except (TypeError, ValueError):
+ pass
+ return True
- config.add_route('ymd', '/{year}/{month}/{day}',
- custom_predicates=(ymd_to_int,))
+
+ config.add_route_predicate('integers', IntegersPredicate)
+ config.add_route('ymd', '/{year}/{month}/{day}',
+ integers=('year', 'month', 'day')
Note that a conversion predicate is still a predicate, so it must return
``True`` or ``False``. A predicate that does *only* conversion, such as the one
@@ -1157,18 +1175,26 @@ expressions specifying requirements for that marker. For instance:
.. code-block:: python
:linenos:
- def integers(*segment_names):
- def predicate(info, request):
+ class IntegersPredicate:
+
+ def __init__(self, val):
+ self.segment_names = val
+
+ def text(self):
+ return 'integers = %s' % (self.segment_names,)
+
+ phash = text
+
+ def __call__(self, info, request):
match = info['match']
- for segment_name in segment_names:
+ for segment_name in self.segment_names:
match[segment_name] = int(match[segment_name])
return True
- return predicate
- ymd_to_int = integers('year', 'month', 'day')
+ config.add_route_predicate('integers', IntegersPredicate)
config.add_route('ymd', '/{year:\d+}/{month:\d+}/{day:\d+}',
- custom_predicates=(ymd_to_int,))
+ integers=('year', 'month', 'day')
Now the try/except is no longer needed because the route will not match at all
unless these markers match ``\d+`` which requires them to be valid digits for
@@ -1199,61 +1225,42 @@ route in a set of route predicates:
.. code-block:: python
:linenos:
- def twenty_ten(info, request):
- if info['route'].name in ('ymd', 'ym', 'y'):
- return info['match']['year'] == '2010'
-
- config.add_route('y', '/{year}', custom_predicates=(twenty_ten,))
- config.add_route('ym', '/{year}/{month}', custom_predicates=(twenty_ten,))
- config.add_route('ymd', '/{year}/{month}/{day}',
- custom_predicates=(twenty_ten,))
-
-The above predicate, when added to a number of route configurations ensures
-that the year match argument is '2010' if and only if the route name is 'ymd',
-'ym', or 'y'.
-
-You can also caption the predicates by setting the ``__text__`` attribute. This
-will help you with the ``pviews`` command (see
-:ref:`displaying_application_routes`) and the ``pyramid_debugtoolbar``.
-
-If a predicate is a class, just add ``__text__`` property in a standard manner.
-
-.. code-block:: python
- :linenos:
-
- class DummyCustomPredicate1(object):
- def __init__(self):
- self.__text__ = 'my custom class predicate'
+ class TwentyTenPredicate:
+ def text(self):
+ return "twenty_ten = True"
- class DummyCustomPredicate2(object):
- __text__ = 'my custom class predicate'
+ phash = text
-If a predicate is a method, you'll need to assign it after method declaration
-(see `PEP 232 <https://www.python.org/dev/peps/pep-0232/>`_).
+ def __call__(self, info, request):
+ if info['route'].name in ('ymd', 'ym', 'y'):
+ return info['match']['year'] == '2010'
-.. code-block:: python
- :linenos:
+ config.add_route_predicate('twenty_ten', TwentyTenPredicate)
+ config.add_route('y', '/{year}', twenty_ten=True)
+ config.add_route('ym', '/{year}/{month}', twenty_ten=True)
+ config.add_route('ymd', '/{year}/{month}/{day}', twenty_ten=True)
- def custom_predicate():
- pass
- custom_predicate.__text__ = 'my custom method predicate'
-
-If a predicate is a classmethod, using ``@classmethod`` will not work, but you
-can still easily do it by wrapping it in a classmethod call.
+The above predicate, when added to a number of route configurations ensures
+that the year match argument is ``'2010'`` if and only if the route name is
+``'ymd'``, ``'ym'``, or ``'y'``.
-.. code-block:: python
- :linenos:
+The ``text`` method is a way to caption the predicates. This
+will help you with the ``pviews`` command (see
+:ref:`displaying_application_routes`) and the
+:term:`pyramid_debugtoolbar`.
- def classmethod_predicate():
- pass
- classmethod_predicate.__text__ = 'my classmethod predicate'
- classmethod_predicate = classmethod(classmethod_predicate)
+The ``phash`` method should return a string that uniquely identifies a
+specific predicate (the name means *predicate hash*). A good way to do
+that is to use the same argument name and value that in the call to
+``add_route``, like in the examples above.
-The same will work with ``staticmethod``, using ``staticmethod`` instead of
-``classmethod``.
+.. XXX add note about predicate matching for boolean custom predicates?
.. seealso::
+ See :ref:`registering_thirdparty_predicates` for more information about
+ custom view, route and subscriber predicates.
+
See also :class:`pyramid.interfaces.IRoute` for more API documentation
about route objects.
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index 6a49e02a5..eb5233e84 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -317,6 +317,8 @@ Non-Predicate Arguments
.. versionadded:: 1.8
+.. _predicate_view_args:
+
Predicate Arguments
+++++++++++++++++++
@@ -506,20 +508,22 @@ configured view.
``custom_predicates``
If ``custom_predicates`` is specified, it must be a sequence of references to
- custom predicate callables. Use custom predicates when no set of predefined
- predicates do what you need. Custom predicates can be combined with
+ custom predicate callables. Custom predicates can be combined with
predefined predicates as necessary. Each custom predicate callable should
accept two arguments, ``context`` and ``request``, and should return either
``True`` or ``False`` after doing arbitrary evaluation of the context
resource and/or the request. If all callables return ``True``, the
associated view callable will be considered viable for a given request.
+ This parameter is kept around for backward compatibility.
- If ``custom_predicates`` is not specified, no custom predicates are used.
+ .. deprecated:: 1.5
+ See section below for new-style custom predicates.
-``predicates``
- Pass a key/value pair here to use a third-party predicate registered via
- :meth:`pyramid.config.Configurator.add_view_predicate`. More than one
- key/value pair can be used at the same time. See
+``**predicates``
+ Extra keyword parameters are used to invoke custom predicates, defined
+ in your app or by third-party packages extending Pyramid and registered via
+ :meth:`pyramid.config.Configurator.add_view_predicate`. Use custom predicates
+ when no set of predefined predicates do what you need. See
:ref:`view_and_route_predicates` for more information about third-party
predicates.
diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst
index 062693d24..fdd135331 100644
--- a/docs/quick_tour.rst
+++ b/docs/quick_tour.rst
@@ -478,7 +478,7 @@ more to offer:
- One route leading to multiple views, based on information in the request or
data such as ``request_param``, ``request_method``, ``accept``, ``header``,
- ``xhr``, ``containment``, and ``custom_predicates``
+ ``xhr``, ``containment``, and custom predicates.
.. seealso:: See also:
:ref:`Quick Tutorial View Classes <qtut_view_classes>`, :ref:`Quick
diff --git a/src/pyramid/config/routes.py b/src/pyramid/config/routes.py
index 44fbb9c46..cc3a87b2e 100644
--- a/src/pyramid/config/routes.py
+++ b/src/pyramid/config/routes.py
@@ -40,7 +40,7 @@ class RoutesConfiguratorMixin(object):
inherit_slash=None,
**predicates
):
- """ Add a :term:`route configuration` to the current
+ r""" Add a :term:`route configuration` to the current
configuration state, as well as possibly a :term:`view
configuration` to be used to specify a :term:`view callable`
that will be invoked when this route matches. The arguments
@@ -283,6 +283,8 @@ class RoutesConfiguratorMixin(object):
.. versionadded:: 1.4a4
+ .. deprecated:: 2.0
+
custom_predicates
.. deprecated:: 1.5
@@ -302,14 +304,14 @@ class RoutesConfiguratorMixin(object):
:ref:`custom_route_predicates` for more information about
``info``.
- predicates
+ \*\*predicates
- Pass a key/value pair here to use a third-party predicate
+ Pass extra keyword parameters to use custom or third-party predicates
registered via
:meth:`pyramid.config.Configurator.add_route_predicate`. More than
- one key/value pair can be used at the same time. See
+ one custom predicate can be used at the same time. See
:ref:`view_and_route_predicates` for more information about
- third-party predicates.
+ custom predicates.
.. versionadded:: 1.4
diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py
index 2cc5e8144..20f20b5e8 100644
--- a/src/pyramid/config/views.py
+++ b/src/pyramid/config/views.py
@@ -266,7 +266,7 @@ class ViewsConfiguratorMixin(object):
exception_only=False,
**view_options
):
- """ Add a :term:`view configuration` to the current
+ r""" Add a :term:`view configuration` to the current
configuration state. Arguments to ``add_view`` are broken
down below into *predicate* arguments and *non-predicate*
arguments. Predicate arguments narrow the circumstances in
@@ -723,6 +723,8 @@ class ViewsConfiguratorMixin(object):
.. versionadded:: 1.4a4
+ .. deprecated:: 2.0
+
custom_predicates
.. deprecated:: 1.5
@@ -740,14 +742,14 @@ class ViewsConfiguratorMixin(object):
obsoletes this argument, but it is kept around for backwards
compatibility.
- view_options
+ \*\*view_options
- Pass a key/value pair here to use a third-party predicate or set a
- value for a view deriver. See
+ Pass extra keyword parameters to use custom or third-party predicates
+ or set a value for a view deriver. See
:meth:`pyramid.config.Configurator.add_view_predicate` and
:meth:`pyramid.config.Configurator.add_view_deriver`. See
:ref:`view_and_route_predicates` for more information about
- third-party predicates and :ref:`view_derivers` for information
+ custom predicates and :ref:`view_derivers` for information
about view derivers.
.. versionadded: 1.4a1