diff options
| author | Chris McDonough <chrism@plope.com> | 2011-09-09 03:09:28 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-09-09 03:09:28 -0400 |
| commit | cda7f6b367728352fb443d046752379e9f401230 (patch) | |
| tree | 9731b292787064867d429a270c9b9bffa162b36b | |
| parent | 41cb3afe29320abb4e20a951863c0ae4a64eba67 (diff) | |
| download | pyramid-cda7f6b367728352fb443d046752379e9f401230.tar.gz pyramid-cda7f6b367728352fb443d046752379e9f401230.tar.bz2 pyramid-cda7f6b367728352fb443d046752379e9f401230.zip | |
- The route prefix was not taken into account when a static view was added in
an "include". See https://github.com/Pylons/pyramid/issues/266 .
| -rw-r--r-- | CHANGES.txt | 9 | ||||
| -rw-r--r-- | pyramid/config/views.py | 45 | ||||
| -rw-r--r-- | pyramid/interfaces.py | 2 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_views.py | 157 | ||||
| -rw-r--r-- | pyramid/tests/test_url.py | 4 |
5 files changed, 126 insertions, 91 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index c62f0a34b..a82d3b336 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,12 @@ +Next release +============ + +Bug Fixes +--------- + +- The route prefix was not taken into account when a static view was added in + an "include". See https://github.com/Pylons/pyramid/issues/266 . + 1.2b2 (2011-09-08) ================== diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 078408914..1612d9a65 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -1386,11 +1386,10 @@ class ViewsConfiguratorMixin(object): spec = self._make_spec(path) info = self.registry.queryUtility(IStaticURLInfo) if info is None: - info = StaticURLInfo(self) + info = StaticURLInfo() self.registry.registerUtility(info, IStaticURLInfo) - info.add(name, spec, **kw) - + info.add(self, name, spec, **kw) def isexception(o): if IInterface.providedBy(o): @@ -1405,25 +1404,26 @@ def isexception(o): class StaticURLInfo(object): implements(IStaticURLInfo) - route_url = staticmethod(route_url) # for testing only - - def __init__(self, config): - self.config = config - self.registrations = [] + def _get_registrations(self, registry): + try: + reg = registry._static_url_registrations + except AttributeError: + reg = registry._static_url_registrations = [] + return reg def generate(self, path, request, **kw): - for (name, spec, is_url) in self.registrations: + for (name, spec, is_url) in self._get_registrations(request.registry): if path.startswith(spec): subpath = path[len(spec):] if is_url: return urljoin(name, subpath) else: kw['subpath'] = subpath - return self.route_url(name, request, **kw) + return request.route_url(name, **kw) raise ValueError('No static URL definition matching %s' % path) - def add(self, name, spec, **extra): + def add(self, config, name, spec, **extra): # This feature only allows for the serving of a directory and # the files contained within, not of a single asset; # appending a slash here if the spec doesn't have one is @@ -1442,15 +1442,17 @@ class StaticURLInfo(object): # make sure it ends with a slash name = name + '/' - names = [ t[0] for t in self.registrations ] + registrations = self._get_registrations(config.registry) + + names = [ t[0] for t in registrations ] if name in names: idx = names.index(name) - self.registrations.pop(idx) + registrations.pop(idx) if urlparse(name)[0]: # it's a URL - self.registrations.append((name, spec, True)) + registrations.append((name, spec, True)) else: # it's a view name cache_max_age = extra.pop('cache_max_age', None) @@ -1485,9 +1487,14 @@ class StaticURLInfo(object): # register a route using the computed view, permission, and # pattern, plus any extras passed to us via add_static_view pattern = "%s*subpath" % name # name already ends with slash - self.config.add_route(name, pattern, **extra) - self.config.add_view(route_name=name, view=view, - permission=permission, context=context, - renderer=renderer, attr=attr) - self.registrations.append((name, spec, False)) + config.add_route(name, pattern, **extra) + config.add_view( + route_name=name, + view=view, + permission=permission, + context=context, + renderer=renderer, + attr=attr + ) + registrations.append((name, spec, False)) diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index 775c571cf..a0f27dd7a 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -507,7 +507,7 @@ class IRouteRequest(Interface): class IStaticURLInfo(Interface): """ A policy for generating URLs to static assets """ - def add(name, spec, **extra): + def add(config, name, spec, **extra): """ Add a new static info registration """ def generate(path, request, **kw): diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 484d49c2f..3876f1e6c 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -1438,7 +1438,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): 'pyramid.tests.test_config:files') self.assertEqual( info.added, - [('static', 'pyramid.tests.test_config:files', {})]) + [(config, 'static', 'pyramid.tests.test_config:files', {})]) def test_add_static_view_package_here_relative(self): from pyramid.interfaces import IStaticURLInfo @@ -1448,7 +1448,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): config.add_static_view('static', 'files') self.assertEqual( info.added, - [('static', 'pyramid.tests.test_config:files', {})]) + [(config, 'static', 'pyramid.tests.test_config:files', {})]) def test_add_static_view_absolute(self): import os @@ -1460,7 +1460,7 @@ class TestViewsConfigurationMixin(unittest.TestCase): static_path = os.path.join(here, 'files') config.add_static_view('static', static_path) self.assertEqual(info.added, - [('static', static_path, {})]) + [(config, 'static', static_path, {})]) def test_set_forbidden_view(self): from pyramid.renderers import null_renderer @@ -3258,8 +3258,24 @@ class TestStaticURLInfo(unittest.TestCase): from pyramid.config.views import StaticURLInfo return StaticURLInfo - def _makeOne(self, config): - return self._getTargetClass()(config) + def _makeOne(self): + return self._getTargetClass()() + + def _makeConfig(self, registrations=None): + config = DummyConfig() + registry = DummyRegistry() + if registrations is not None: + registry._static_url_registrations = registrations + config.registry = registry + return config + + def _makeRequest(self): + request = DummyRequest() + request.registry = DummyRegistry() + return request + + def _assertRegistrations(self, config, expected): + self.assertEqual(config.registry._static_url_registrations, expected) def test_verifyClass(self): from pyramid.interfaces import IStaticURLInfo @@ -3269,142 +3285,145 @@ class TestStaticURLInfo(unittest.TestCase): def test_verifyObject(self): from pyramid.interfaces import IStaticURLInfo from zope.interface.verify import verifyObject - verifyObject(IStaticURLInfo, self._makeOne(None)) - - def test_ctor(self): - info = self._makeOne(None) - self.assertEqual(info.registrations, []) - self.assertEqual(info.config, None) + verifyObject(IStaticURLInfo, self._makeOne()) def test_generate_missing(self): - inst = self._makeOne(None) - request = DummyRequest() + inst = self._makeOne() + request = self._makeRequest() self.assertRaises(ValueError, inst.generate, 'path', request) def test_generate_registration_miss(self): - inst = self._makeOne(None) - inst.registrations = [('name', 'spec', False), - ('http://example.com/foo/', 'package:path/',True)] - request = DummyRequest() + inst = self._makeOne() + registrations = [('name', 'spec', False), + ('http://example.com/foo/', 'package:path/',True)] + inst._get_registrations = lambda *x: registrations + request = self._makeRequest() result = inst.generate('package:path/abc', request) self.assertEqual(result, 'http://example.com/foo/abc') def test_generate_slash_in_name1(self): - inst = self._makeOne(None) - inst.registrations = [('http://example.com/foo/', 'package:path/',True)] - request = DummyRequest() + inst = self._makeOne() + registrations = [('http://example.com/foo/', 'package:path/',True)] + inst._get_registrations = lambda *x: registrations + request = self._makeRequest() result = inst.generate('package:path/abc', request) self.assertEqual(result, 'http://example.com/foo/abc') def test_generate_slash_in_name2(self): - inst = self._makeOne(None) - inst.registrations = [('http://example.com/foo/', 'package:path/',True)] - request = DummyRequest() + inst = self._makeOne() + registrations = [('http://example.com/foo/', 'package:path/',True)] + inst._get_registrations = lambda *x: registrations + request = self._makeRequest() result = inst.generate('package:path/', request) self.assertEqual(result, 'http://example.com/foo/') def test_generate_route_url(self): - inst = self._makeOne(None) - inst.registrations = [('viewname/', 'package:path/', False)] - def route_url(n, r, **kw): + inst = self._makeOne() + registrations = [('viewname/', 'package:path/', False)] + inst._get_registrations = lambda *x: registrations + def route_url(n, **kw): self.assertEqual(n, 'viewname/') - self.assertEqual(r, request) self.assertEqual(kw, {'subpath':'abc', 'a':1}) return 'url' - request = DummyRequest() - inst.route_url = route_url + request = self._makeRequest() + request.route_url = route_url result = inst.generate('package:path/abc', request, a=1) self.assertEqual(result, 'url') def test_add_already_exists(self): - inst = self._makeOne(None) - inst.registrations = [('http://example.com/', 'package:path/', True)] - inst.add('http://example.com', 'anotherpackage:path') + inst = self._makeOne() + config = self._makeConfig( + [('http://example.com/', 'package:path/', True)]) + inst.add(config, 'http://example.com', 'anotherpackage:path') expected = [('http://example.com/', 'anotherpackage:path/', True)] - self.assertEqual(inst.registrations, expected) + self._assertRegistrations(config, expected) def test_add_url_withendslash(self): - inst = self._makeOne(None) - inst.add('http://example.com/', 'anotherpackage:path') + inst = self._makeOne() + config = self._makeConfig() + inst.add(config, 'http://example.com/', 'anotherpackage:path') expected = [('http://example.com/', 'anotherpackage:path/', True)] - self.assertEqual(inst.registrations, expected) + self._assertRegistrations(config, expected) def test_add_url_noendslash(self): - inst = self._makeOne(None) - inst.add('http://example.com', 'anotherpackage:path') + inst = self._makeOne() + config = self._makeConfig() + inst.add(config, 'http://example.com', 'anotherpackage:path') expected = [('http://example.com/', 'anotherpackage:path/', True)] - self.assertEqual(inst.registrations, expected) + self._assertRegistrations(config, expected) def test_add_viewname(self): from pyramid.security import NO_PERMISSION_REQUIRED from pyramid.static import static_view - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1) + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1) expected = [('view/', 'anotherpackage:path/', False)] - self.assertEqual(inst.registrations, expected) + self._assertRegistrations(config, expected) self.assertEqual(config.route_args, ('view/', 'view/*subpath')) self.assertEqual(config.view_kw['permission'], NO_PERMISSION_REQUIRED) self.assertEqual(config.view_kw['view'].__class__, static_view) def test_add_viewname_with_permission(self): - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1, + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, permission='abc') self.assertEqual(config.view_kw['permission'], 'abc') def test_add_viewname_with_view_permission(self): - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1, + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, view_permission='abc') self.assertEqual(config.view_kw['permission'], 'abc') def test_add_viewname_with_view_context(self): - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1, + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, view_context=DummyContext) self.assertEqual(config.view_kw['context'], DummyContext) def test_add_viewname_with_view_for(self): - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1, + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, view_for=DummyContext) self.assertEqual(config.view_kw['context'], DummyContext) def test_add_viewname_with_for_(self): - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1, + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, for_=DummyContext) self.assertEqual(config.view_kw['context'], DummyContext) def test_add_viewname_with_view_renderer(self): - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1, + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, view_renderer='mypackage:templates/index.pt') self.assertEqual(config.view_kw['renderer'], 'mypackage:templates/index.pt') def test_add_viewname_with_renderer(self): - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1, + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, renderer='mypackage:templates/index.pt') self.assertEqual(config.view_kw['renderer'], 'mypackage:templates/index.pt') def test_add_viewname_with_view_attr(self): - config = DummyConfig() - inst = self._makeOne(config) - inst.add('view', 'anotherpackage:path', cache_max_age=1, + config = self._makeConfig() + inst = self._makeOne() + inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1, view_attr='attr') self.assertEqual(config.view_kw['attr'], 'attr') +class DummyRegistry: + pass class DummyRequest: subpath = () @@ -3495,5 +3514,5 @@ class DummyStaticURLInfo: def __init__(self): self.added = [] - def add(self, name, spec, **kw): - self.added.append((name, spec, kw)) + def add(self, config, name, spec, **kw): + self.added.append((config, name, spec, kw)) diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index a23b75e73..8b95374fb 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -385,9 +385,9 @@ class TestURLMethodsMixin(unittest.TestCase): import os from pyramid.interfaces import IStaticURLInfo from pyramid.config.views import StaticURLInfo - info = StaticURLInfo(self.config) + info = StaticURLInfo() here = os.path.abspath(os.path.dirname(__file__)) - info.add('absstatic', here) + info.add(self.config, 'absstatic', here) request = self._makeOne() registry = request.registry registry.registerUtility(info, IStaticURLInfo) |
