summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-01-27 01:24:35 +0000
committerChris McDonough <chrism@agendaless.com>2009-01-27 01:24:35 +0000
commit9259571f8bce01374060c198e990b1650b5e257e (patch)
tree7ce3eb7138d3d5237c0b287fa1ebc1819ce52d6f
parent01132b859acb3850eb6d9de6a1d8c2d005165fe3 (diff)
downloadpyramid-9259571f8bce01374060c198e990b1650b5e257e.tar.gz
pyramid-9259571f8bce01374060c198e990b1650b5e257e.tar.bz2
pyramid-9259571f8bce01374060c198e990b1650b5e257e.zip
- There is an indirection in ``repoze.bfg.url.model_url`` now that
consults a utility to generate the base model url (without extra elements or a query string). Eventually this will service virtual hosting; for now it's undocumented and should not be hooked.
-rw-r--r--CHANGES.txt11
-rw-r--r--repoze/bfg/interfaces.py5
-rw-r--r--repoze/bfg/tests/test_url.py47
-rw-r--r--repoze/bfg/url.py50
4 files changed, 98 insertions, 15 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 863b605a6..21f888194 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,14 @@
+Next Release
+============
+
+Implementation Changes
+----------------------
+
+- There is an indirection in ``repoze.bfg.url.model_url`` now that
+ consults a utility to generate the base model url (without extra
+ elements or a query string). Eventually this will service virtual
+ hosting; for now it's undocumented and should not be hooked.
+
0.6.5 (2009-01-26)
==================
diff --git a/repoze/bfg/interfaces.py b/repoze/bfg/interfaces.py
index 42c6d2a11..7d4286ca3 100644
--- a/repoze/bfg/interfaces.py
+++ b/repoze/bfg/interfaces.py
@@ -201,3 +201,8 @@ class IUnauthorizedAppFactory(Interface):
``message`` key in the WSGI environ provides information
pertaining to the reason for the unauthorized."""
+class IURLGenerator(Interface):
+ """ A utility which provides virtual hosting services
+ """
+ def model_url(model, request):
+ """ Return a URL that points to the model """
diff --git a/repoze/bfg/tests/test_url.py b/repoze/bfg/tests/test_url.py
index 90118bd34..a1aa84890 100644
--- a/repoze/bfg/tests/test_url.py
+++ b/repoze/bfg/tests/test_url.py
@@ -1,5 +1,51 @@
import unittest
+class DefaultURLGeneratorTests(unittest.TestCase):
+ def _makeOne(self):
+ return self._getTargetClass()()
+
+ def _getTargetClass(self):
+ from repoze.bfg.url import DefaultURLGenerator
+ return DefaultURLGenerator
+
+ def test_class_conforms_to_IURLGenerator(self):
+ from zope.interface.verify import verifyClass
+ from repoze.bfg.interfaces import IURLGenerator
+ verifyClass(IURLGenerator, self._getTargetClass())
+
+ def test_instance_conforms_to_IURLGenerator(self):
+ from zope.interface.verify import verifyObject
+ from repoze.bfg.interfaces import IURLGenerator
+ context = DummyContext()
+ verifyObject(IURLGenerator, self._makeOne())
+
+ def test_model_url_withlineage(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()
+ gen = self._makeOne()
+ result = gen.model_url(baz, request)
+ self.assertEqual(result, 'http://example.com:5432/foo%20/bar/baz/')
+
+ def test_model_url_nolineage(self):
+ context = DummyContext()
+ context.__name__ = ''
+ context.__parent__ = None
+ request = DummyRequest()
+ gen = self._makeOne()
+ result = gen.model_url(context, request)
+ self.assertEqual(result, 'http://example.com:5432/')
+
class ModelURLTests(unittest.TestCase):
def _callFUT(self, model, request, *elements, **kw):
from repoze.bfg.url import model_url
@@ -20,7 +66,6 @@ class ModelURLTests(unittest.TestCase):
baz.__name__ = 'baz'
request = DummyRequest()
result = self._callFUT(baz, request, 'this/theotherthing', 'that')
-
self.assertEqual(
result,
'http://example.com:5432/foo%20/bar/baz/this/theotherthing/that')
diff --git a/repoze/bfg/url.py b/repoze/bfg/url.py
index 05e16451c..a51333353 100644
--- a/repoze/bfg/url.py
+++ b/repoze/bfg/url.py
@@ -3,7 +3,27 @@
import re
import urllib
+from zope.component import queryUtility
+from zope.interface import implements
+
from repoze.bfg.location import lineage
+from repoze.bfg.interfaces import IURLGenerator
+
+class DefaultURLGenerator(object):
+ implements(IURLGenerator)
+ def model_url(self, model, request):
+ rpath = []
+ for location in lineage(model):
+ name = location.__name__
+ if name:
+ rpath.append(_urlsegment(name))
+ if rpath:
+ prefix = '/' + '/'.join(reversed(rpath)) + '/'
+ else:
+ prefix = '/'
+ return request.application_url + prefix
+
+default_url_generator = DefaultURLGenerator()
def model_url(model, request, *elements, **kw):
"""
@@ -43,7 +63,7 @@ def model_url(model, request, *elements, **kw):
the resulting string is appended to the generated URL.
.. note:: Python data structures that are passed as ``query``
- which are sequences or dictionaries are turned into a
+ whichare sequences or dictionaries are turned into a
string under the same rules as when run through
urllib.urlencode with the ``doseq`` argument equal to
``True``. This means that sequences can be passed as
@@ -51,22 +71,24 @@ def model_url(model, request, *elements, **kw):
string for each value.
"""
- qs = ''
+ urlgenerator = queryUtility(IURLGenerator)
+ if urlgenerator is None:
+ urlgenerator = default_url_generator
+
+ model_url = urlgenerator.model_url(model, request)
+
if 'query' in kw:
qs = '?' + urlencode(kw['query'], doseq=True)
-
- rpath = []
- for location in lineage(model):
- name = location.__name__
- if name:
- rpath.append(_urlsegment(name))
- prefix = '/'.join(reversed(rpath))
- suffix = '/'.join([_urlsegment(s) for s in elements])
- path = '/'.join([prefix, suffix])
- if not path.startswith('/'):
- path = '/' + path
+ else:
+ qs = ''
+
+ if elements:
+ suffix = '/'.join([_urlsegment(s) for s in elements])
+ else:
+ suffix = ''
+
app_url = request.application_url # never ends in a slash
- return app_url + path + qs
+ return model_url + suffix + qs
def urlencode(query, doseq=False):
"""