summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2008-07-29 01:54:50 +0000
committerChris McDonough <chrism@agendaless.com>2008-07-29 01:54:50 +0000
commit35ff8e696a2c983cee119c936ea12ecb2f7da2c3 (patch)
tree2c4873cac17bc122ed0011574c0551f7370b5927
parent339c73892ba00d640ac7a22dccbd56e360cfea0d (diff)
downloadpyramid-35ff8e696a2c983cee119c936ea12ecb2f7da2c3.tar.gz
pyramid-35ff8e696a2c983cee119c936ea12ecb2f7da2c3.tar.bz2
pyramid-35ff8e696a2c983cee119c936ea12ecb2f7da2c3.zip
0.2.5: add model_url.
-rw-r--r--CHANGES.txt4
-rw-r--r--docs/api/traversal.rst1
-rw-r--r--docs/conf.py4
-rw-r--r--docs/glossary.rst3
-rw-r--r--docs/narr/models.rst2
-rw-r--r--repoze/bfg/tests/test_traversal.py31
-rw-r--r--repoze/bfg/traversal.py23
-rw-r--r--setup.py2
8 files changed, 61 insertions, 9 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index c210d998e..2ae332b0c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,7 @@
+0.2.5
+
+ - Add ``model_url`` API.
+
0.2.4
- Added url-based dispatch.
diff --git a/docs/api/traversal.rst b/docs/api/traversal.rst
index 41d66b2eb..eac63a271 100644
--- a/docs/api/traversal.rst
+++ b/docs/api/traversal.rst
@@ -7,4 +7,5 @@
.. autofunction:: find_interface
+ .. autofunction:: model_url
diff --git a/docs/conf.py b/docs/conf.py
index 979c6d9ac..8d19cf4db 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -51,9 +51,9 @@ copyright = '2008, Agendaless Consulting'
# other places throughout the built documents.
#
# The short X.Y version.
-version = '0.2'
+version = '0.2.5'
# The full version, including alpha/beta/rc tags.
-release = '0.2'
+release = '0.2.5'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 4e88b51d2..27326f539 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -74,7 +74,8 @@ Glossary
Interface
An attribute of an object that determines its type.
Location
- The path to an object in a model graph.
+ The path to an object in a model graph. See :ref:`location_aware`
+ for more information about how to make a model object *location-aware*.
Security policy
An object that provides a mechanism to check authorization using
authentication data and a permission associated with a model. It
diff --git a/docs/narr/models.rst b/docs/narr/models.rst
index efbcd47b2..7df265657 100644
--- a/docs/narr/models.rst
+++ b/docs/narr/models.rst
@@ -58,6 +58,8 @@ instance nodes in the graph:
implement a ``__getitem__``, or if they do, their ``__getitem__``
method must raise a ``KeyError``.
+.. _location_aware:
+
Location-Aware Model Instances
------------------------------
diff --git a/repoze/bfg/tests/test_traversal.py b/repoze/bfg/tests/test_traversal.py
index 5cc7551c0..1ae92dcf7 100644
--- a/repoze/bfg/tests/test_traversal.py
+++ b/repoze/bfg/tests/test_traversal.py
@@ -169,6 +169,33 @@ class FindInterfaceTests(unittest.TestCase):
result = finder(baz, IFoo)
self.assertEqual(result.__name__, 'root')
+class ModelURLTests(unittest.TestCase):
+ def _getFUT(self):
+ from repoze.bfg.traversal import model_url
+ return model_url
+
+ def test_it(self):
+ baz = DummyContext()
+ bar = DummyContext(baz)
+ foo = DummyContext(bar)
+ root = DummyContext(foo)
+ root.__parent__ = None
+ root.__name__ = None
+ foo.__parent__ = root
+ foo.__name__ = 'foo '
+ bar.__parent__ = foo
+ bar.__name__ = 'bar'
+ baz.__parent__ = bar
+ baz.__name__ = 'baz'
+ request = DummyRequest()
+ model_url = self._getFUT()
+ request = DummyRequest()
+ result = model_url(baz, request, 'this/theotherthing', 'that')
+
+ self.assertEqual(
+ result,
+ 'http://example.com:5432/foo%20/bar/baz/this/theotherthing/that')
+
class DummyContext(object):
def __init__(self, next=None):
self.next = next
@@ -179,8 +206,8 @@ class DummyContext(object):
return self.next
class DummyRequest:
- pass
-
+ application_url = 'http://example.com:5432/'
+
class DummyTraverser:
def __init__(self, context):
self.context = context
diff --git a/repoze/bfg/traversal.py b/repoze/bfg/traversal.py
index d0e140375..c72c90e5e 100644
--- a/repoze/bfg/traversal.py
+++ b/repoze/bfg/traversal.py
@@ -1,4 +1,5 @@
import urllib
+import urlparse
from zope.interface import classProvides
from zope.interface import implements
@@ -66,9 +67,25 @@ class ModelGraphTraverser(object):
return ob, name, path
def find_interface(context, interface):
- """ Return an object providing 'interface' anywhere in the parent
- chain of 'context' or None if no object providing that interface
- can be found in the parent chain """
+ """ Return an object providing ``interface`` anywhere in the
+ parent chain of ``context`` or ``None`` if no object providing
+ that interface can be found in the parent chain"""
for location in LocationIterator(context):
if interface.providedBy(location):
return location
+
+def model_url(model, request, *elements):
+ """ Return the absolute URL of the model object based on the
+ ``wsgi.url_scheme``, ``HTTP_HOST`` or ``SERVER_NAME`` in the
+ request, plus any ``SCRIPT_NAME``. Any positional passed in as
+ ``elements`` will be joined by slashes and appended to the
+ generated URL. The passed in elements are *not* URL-quoted. The
+ ``model`` passed in must be :term:`location`-aware."""
+ rpath = []
+ for location in LocationIterator(model):
+ if location.__name__:
+ rpath.append(urllib.quote(location.__name__))
+ path = list(reversed(rpath))
+ path.extend(elements)
+ path = '/'.join(path)
+ return urlparse.urljoin(request.application_url, path)
diff --git a/setup.py b/setup.py
index e0df62e4e..d1d324d68 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@
#
##############################################################################
-__version__ = '0.2.4'
+__version__ = '0.2.5'
import os