summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt11
-rw-r--r--docs/api/traversal.rst2
-rw-r--r--repoze/bfg/tests/test_traversal.py6
-rw-r--r--repoze/bfg/traversal.py56
4 files changed, 69 insertions, 6 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 2f996a932..784e57b81 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,7 +9,13 @@ Features
invoked due to lack of permission. See the "ZCML Hooks" chapter in
the docs for more information.
-- Added Routes ZCML directive attribute explanations.
+- Added Routes ZCML directive attribute explanations in documentation.
+
+- Added a ``traversal_path`` API to the traversal module; see the
+ "traversal" API chapter in the docs. This was a function previously
+ known as ``split_path`` that was not an API but people were using it
+ anyway. Unlike ``split_path`` it now returns a tuple instead of a
+ list (as its values are cached).
Behavior Changes
----------------
@@ -66,6 +72,9 @@ Implementation Changes
- Use a homegrown Unauthorized error instead of
``webob.exc.Unauthorized`` (the latter is slow).
+- the ``repoze.bfg.lru.lru_cached`` decorator now uses functools.wraps
+ in order to make documentation of LRU-cached functions possible.
+
- Various speed micro-tweaks.
Bug Fixes
diff --git a/docs/api/traversal.rst b/docs/api/traversal.rst
index 8195ddec4..d9b4aabfc 100644
--- a/docs/api/traversal.rst
+++ b/docs/api/traversal.rst
@@ -13,6 +13,8 @@
.. autofunction:: model_path
+ .. autofunction:: traversal_path(path)
+
.. note:: A function named ``model_url`` used to be present in this
module. It was moved to :ref:`url_module` in version 0.6.1.
diff --git a/repoze/bfg/tests/test_traversal.py b/repoze/bfg/tests/test_traversal.py
index 6459ed1af..f21cf7d8d 100644
--- a/repoze/bfg/tests/test_traversal.py
+++ b/repoze/bfg/tests/test_traversal.py
@@ -2,10 +2,10 @@ import unittest
from zope.testing.cleanup import cleanUp
-class SplitPathTests(unittest.TestCase):
+class TraversalPathTests(unittest.TestCase):
def _callFUT(self, path):
- from repoze.bfg.traversal import split_path
- return split_path(path)
+ from repoze.bfg.traversal import traversal_path
+ return traversal_path(path)
def test_path_startswith_endswith(self):
self.assertEqual(self._callFUT('/foo/'), (u'foo',))
diff --git a/repoze/bfg/traversal.py b/repoze/bfg/traversal.py
index 7adef4011..d6f92e118 100644
--- a/repoze/bfg/traversal.py
+++ b/repoze/bfg/traversal.py
@@ -20,6 +20,15 @@ deprecated(
model_url = "repoze.bfg.url:model_url",
)
+# ``split_path`` wasn't actually ever an API but people were using it
+# anyway. I turned it into the ``traversal_path`` API in 0.6.5, and
+# generate the below deprecation to give folks a heads up.
+deprecated(
+ "('from repoze.bfg.traversal import split_path' is now deprecated; "
+ "instead use 'from repoze.bfg.traversal import traversal_path')",
+ split_path = "repoze.bfg.traversal:traversal_path",
+ )
+
def find_root(model):
""" Find the root node in the graph to which ``model``
belongs. Note that ``model`` should be :term:`location`-aware.
@@ -101,7 +110,50 @@ def model_path(model, *elements):
return path
@lru_cache(500)
-def split_path(path):
+def traversal_path(path):
+ """ Given a PATH_INFO string (slash-separated path elements),
+ return a tuple representing that path which can be used to
+ traverse a graph. The PATH_INFO is split on slashes, creating a
+ list of segments. Each segment is URL-unquoted, and decoded into
+ Unicode. Each segment is assumed to be encoded using the UTF-8
+ encoding (or a subset, such as ASCII); a TypeError is raised if a
+ segment cannot be decoded. If a segment name is empty or if it is
+ ``.``, it is ignored. If a segment name is ``..``, the previous
+ segment is deleted, and the ``..`` is ignored. Examples:
+
+ ``/``
+
+ ()
+
+ ``/foo/bar/baz``
+
+ (u'foo', u'bar', u'baz')
+
+ ``foo/bar/baz``
+
+ (u'foo', u'bar', u'baz')
+
+ ``/foo/bar/baz/``
+
+ (u'foo', u'bar', u'baz')
+
+ ``/foo//bar//baz/``
+
+ (u'foo', u'bar', u'baz')
+
+ ``/foo/bar/baz/..``
+
+ (u'foo', u'bar')
+
+ ``/my%20archives/hello``
+
+ (u'my archives', u'hello')
+
+ ``/archives/La%20Pe%C3%B1a``
+
+ (u'archives', u'<unprintable unicode>')
+
+ """
while path.startswith('/'):
path = path[1:]
while path.endswith('/'):
@@ -136,7 +188,7 @@ class ModelGraphTraverser(object):
path = environ['PATH_INFO']
except KeyError:
path = '/'
- path = list(split_path(path))
+ path = list(traversal_path(path))
locatable = self.locatable
step = self._step