summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt35
-rw-r--r--docs/glossary.rst22
-rw-r--r--docs/narr/viewconfig.rst14
-rw-r--r--pyramid/config/predicates.py21
-rw-r--r--pyramid/config/views.py17
-rw-r--r--pyramid/tests/test_config/test_predicates.py53
-rw-r--r--pyramid/view.py2
7 files changed, 144 insertions, 20 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 9b3ce1253..4baf81581 100644
--- a/CHANGES.txt
+++ b/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 @@ Bug Fixes
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 @@ Features
``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)
==================
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 96dd826d1..adcf36f7c 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -481,10 +481,24 @@ Glossary
: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"
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index 3c7897969..752e6ad72 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -417,6 +417,20 @@ configured view.
.. 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
diff --git a/pyramid/config/predicates.py b/pyramid/config/predicates.py
index 100c9454e..adbdcbbc0 100644
--- a/pyramid/config/predicates.py
+++ b/pyramid/config/predicates.py
@@ -2,15 +2,16 @@ import re
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 @@ class CheckCSRFTokenPredicate(object):
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
+
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 15263ad04..e52f9d64b 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -1014,6 +1014,22 @@ class ViewsConfiguratorMixin(object):
.. 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 @@ class ViewsConfiguratorMixin(object):
('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)
diff --git a/pyramid/tests/test_config/test_predicates.py b/pyramid/tests/test_config/test_predicates.py
index 2f0ef4132..84d9b184d 100644
--- a/pyramid/tests/test_config/test_predicates.py
+++ b/pyramid/tests/test_config/test_predicates.py
@@ -381,6 +381,59 @@ class TestHeaderPredicate(unittest.TestCase):
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'
diff --git a/pyramid/view.py b/pyramid/view.py
index 76f466b83..51ded423c 100644
--- a/pyramid/view.py
+++ b/pyramid/view.py
@@ -170,7 +170,7 @@ class view_config(object):
``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