summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-09-09 03:09:28 -0400
committerChris McDonough <chrism@plope.com>2011-09-09 03:09:28 -0400
commitcda7f6b367728352fb443d046752379e9f401230 (patch)
tree9731b292787064867d429a270c9b9bffa162b36b
parent41cb3afe29320abb4e20a951863c0ae4a64eba67 (diff)
downloadpyramid-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.txt9
-rw-r--r--pyramid/config/views.py45
-rw-r--r--pyramid/interfaces.py2
-rw-r--r--pyramid/tests/test_config/test_views.py157
-rw-r--r--pyramid/tests/test_url.py4
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)