Chris McDonough
2012-10-26 c25a8fd5d2895a117d8eb77162ed8388f0482674
- New ``physical_path`` view predicate.  If specified, this value should be a
string or a tuple representing the physical traversal path of the context
found via traversal for this predicate to match as true. For example:
``physical_path='/'`` or ``physical_path='/a/b/c'`` or ``physical_path=('',
'a', 'b', 'c')``. This is not a path prefix match or a regex, it's a
whole-path match. It's useful when you want to always potentially show a
view when some object is traversed to, but you can't be sure about what kind
of object it will be, so you can't use the ``context`` predicate. The
individual path elements inbetween slash characters or in tuple elements
should be the Unicode representation of the name of the resource and should
not be encoded in any way.
7 files modified
164 ■■■■ changed files
CHANGES.txt 35 ●●●●● patch | view | raw | blame | history
docs/glossary.rst 22 ●●●● patch | view | raw | blame | history
docs/narr/viewconfig.rst 14 ●●●●● patch | view | raw | blame | history
pyramid/config/predicates.py 21 ●●●●● patch | view | raw | blame | history
pyramid/config/views.py 17 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_predicates.py 53 ●●●●● patch | view | raw | blame | history
pyramid/view.py 2 ●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,19 +1,6 @@
Next release
============
Features
--------
- Allow multiple values to be specified to the ``request_param`` view/route
  predicate as a sequence.  Previously only a single string value was allowed.
  See https://github.com/Pylons/pyramid/pull/705
- Comments with references to documentation sections placed in scaffold
  ``.ini`` files.
- Added an HTTP Basic authentication policy
  at ``pyramid.authentication.BasicAuthAuthenticationPolicy``.
Bug Fixes
---------
@@ -40,6 +27,16 @@
Features
--------
- Allow multiple values to be specified to the ``request_param`` view/route
  predicate as a sequence.  Previously only a single string value was allowed.
  See https://github.com/Pylons/pyramid/pull/705
- Comments with references to documentation sections placed in scaffold
  ``.ini`` files.
- Added an HTTP Basic authentication policy
  at ``pyramid.authentication.BasicAuthAuthenticationPolicy``.
- The Configurator ``testing_securitypolicy`` method now returns the policy
  object it creates.
@@ -56,6 +53,18 @@
  ``remembered`` value on the policy, which is the value of the ``principal``
  argument it's called with when its ``remember`` method is called.
- New ``physical_path`` view predicate.  If specified, this value should be a
  string or a tuple representing the physical traversal path of the context
  found via traversal for this predicate to match as true.  For example:
  ``physical_path='/'`` or ``physical_path='/a/b/c'`` or ``physical_path=('',
  'a', 'b', 'c')``.  This is not a path prefix match or a regex, it's a
  whole-path match.  It's useful when you want to always potentially show a
  view when some object is traversed to, but you can't be sure about what kind
  of object it will be, so you can't use the ``context`` predicate.  The
  individual path elements inbetween slash characters or in tuple elements
  should be the Unicode representation of the name of the resource and should
  not be encoded in any way.
1.4a2 (2012-09-27)
==================
docs/glossary.rst
@@ -481,10 +481,24 @@
     :app:`Pyramid` to form a workflow system.
   virtual root
     A resource object representing the "virtual" root of a request; this
     is typically the physical root object (the object returned by the
     application root factory) unless :ref:`vhosting_chapter` is in
     use.
     A resource object representing the "virtual" root of a request; this is
     typically the :term:`physical root` object unless :ref:`vhosting_chapter`
     is in use.
   physical root
     The object returned by the application :term:`root factory`.  Unlike the
     the :term:`virtual root` of a request, it is not impacted by
     :ref:`vhosting_chapter`: it will always be the actual object returned by
     the root factory, never a subobject.
   physical path
     The path required by a traversal which resolve a :term:`resource` starting
     from the :term:`physical root`.  For example, the physical path of the
     ``abc`` subobject of the physical root object is ``/abc``.  Physical paths
     can also be specified as tuples where the first element is the empty
     string (representing the root), and every other element is a Unicode
     object, e.g. ``('', 'abc')``.  Physical paths are also sometimes called
     "traversal paths".
   lineage
     An ordered sequence of objects based on a ":term:`location` -aware"
docs/narr/viewconfig.rst
@@ -417,6 +417,20 @@
  .. versionadded:: 1.4a2
``physical_path``
  If specified, this value should be a string or a tuple representing the
  :term:`physical path` of the context found via traversal for this predicate
  to match as true.  For example: ``physical_path='/'`` or
  ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.  This is
  not a path prefix match or a regex, it's a whole-path match.  It's useful
  when you want to always potentially show a view when some object is traversed
  to, but you can't be sure about what kind of object it will be, so you can't
  use the ``context`` predicate.  The individual path elements inbetween slash
  characters or in tuple elements should be the Unicode representation of the
  name of the resource and should not be encoded in any way.
  .. versionadded:: 1.4a3
``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
pyramid/config/predicates.py
@@ -2,15 +2,16 @@
from pyramid.exceptions import ConfigurationError
from pyramid.compat import is_nonstr_iter
from pyramid.traversal import (
    find_interface,
    traversal_path,
    resource_path_tuple
    )
from pyramid.urldispatch import _compile_route
from pyramid.util import object_description
from pyramid.session import check_csrf_token
from .util import as_sorted_tuple
@@ -250,3 +251,19 @@
            return self.check_csrf_token(request, val, raises=False)
        return True
class PhysicalPathPredicate(object):
    def __init__(self, val, config):
        if is_nonstr_iter(val):
            self.val = tuple(val)
        else:
            val = tuple(filter(None, val.split('/')))
            self.val = ('',) + val
    def text(self):
        return 'physical_path = %s' % (self.val,)
    phash = text
    def __call__(self, context, request):
        return resource_path_tuple(context) == self.val
pyramid/config/views.py
@@ -1014,6 +1014,22 @@
         
          .. versionadded:: 1.4a2
        physical_path
          If specified, this value should be a string or a tuple representing
          the :term:`physical path` of the context found via traversal for this
          predicate to match as true.  For example: ``physical_path='/'`` or
          ``physical_path='/a/b/c'`` or ``physical_path=('', 'a', 'b', 'c')``.
          This is not a path prefix match or a regex, it's a whole-path match.
          It's useful when you want to always potentially show a view when some
          object is traversed to, but you can't be sure about what kind of
          object it will be, so you can't use the ``context`` predicate.  The
          individual path elements inbetween slash characters or in tuple
          elements should be the Unicode representation of the name of the
          resource and should not be encoded in any way.
          .. versionadded:: 1.4a3
        custom_predicates
          This value should be a sequence of references to custom
@@ -1370,6 +1386,7 @@
            ('request_type', p.RequestTypePredicate),
            ('match_param', p.MatchParamPredicate),
            ('check_csrf', p.CheckCSRFTokenPredicate),
            ('physical_path', p.PhysicalPathPredicate),
            ('custom', p.CustomPredicate),
            ):
            self.add_view_predicate(name, factory)
pyramid/tests/test_config/test_predicates.py
@@ -381,6 +381,59 @@
        inst = self._makeOne(r'abc:\d+')
        self.assertEqual(inst.phash(), r'header abc=\d+')
class Test_PhysicalPathPredicate(unittest.TestCase):
    def _makeOne(self, val, config):
        from pyramid.config.predicates import PhysicalPathPredicate
        return PhysicalPathPredicate(val, config)
    def test_text(self):
        inst = self._makeOne('/', None)
        self.assertEqual(inst.text(), "physical_path = ('',)")
    def test_phash(self):
        inst = self._makeOne('/', None)
        self.assertEqual(inst.phash(), "physical_path = ('',)")
    def test_it_call_val_tuple_True(self):
        inst = self._makeOne(('', 'abc'), None)
        root = Dummy()
        root.__name__ = ''
        root.__parent__ = None
        context = Dummy()
        context.__name__ = 'abc'
        context.__parent__ = root
        self.assertTrue(inst(context, None))
    def test_it_call_val_list_True(self):
        inst = self._makeOne(['', 'abc'], None)
        root = Dummy()
        root.__name__ = ''
        root.__parent__ = None
        context = Dummy()
        context.__name__ = 'abc'
        context.__parent__ = root
        self.assertTrue(inst(context, None))
    def test_it_call_val_str_True(self):
        inst = self._makeOne('/abc', None)
        root = Dummy()
        root.__name__ = ''
        root.__parent__ = None
        context = Dummy()
        context.__name__ = 'abc'
        context.__parent__ = root
        self.assertTrue(inst(context, None))
    def test_it_call_False(self):
        inst = self._makeOne('/', None)
        root = Dummy()
        root.__name__ = ''
        root.__parent__ = None
        context = Dummy()
        context.__name__ = 'abc'
        context.__parent__ = root
        self.assertFalse(inst(context, None))
class predicate(object):
    def __repr__(self):
        return 'predicate'
pyramid/view.py
@@ -170,7 +170,7 @@
    ``request_type``, ``route_name``, ``request_method``, ``request_param``,
    ``containment``, ``xhr``, ``accept``, ``header``, ``path_info``,
    ``custom_predicates``, ``decorator``, ``mapper``, ``http_cache``,
    ``match_param``, ``csrf_token``, and ``predicates``.
    ``match_param``, ``csrf_token``, ``physical_path``, and ``predicates``.
    The meanings of these arguments are the same as the arguments passed to
    :meth:`pyramid.config.Configurator.add_view`.  If any argument is left