diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-01-27 01:24:35 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-01-27 01:24:35 +0000 |
| commit | 9259571f8bce01374060c198e990b1650b5e257e (patch) | |
| tree | 7ce3eb7138d3d5237c0b287fa1ebc1819ce52d6f | |
| parent | 01132b859acb3850eb6d9de6a1d8c2d005165fe3 (diff) | |
| download | pyramid-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.txt | 11 | ||||
| -rw-r--r-- | repoze/bfg/interfaces.py | 5 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_url.py | 47 | ||||
| -rw-r--r-- | repoze/bfg/url.py | 50 |
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): """ |
