Skip to content

Commit

Permalink
fix caching of template registrations that reference macros
Browse files Browse the repository at this point in the history
  • Loading branch information
mcdonc committed Oct 5, 2012
1 parent 24e14af commit fa587ef
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 15 deletions.
31 changes: 19 additions & 12 deletions pyramid/renderers.py
Expand Up @@ -367,6 +367,12 @@ def _render(value, system):


@implementer(IChameleonLookup) @implementer(IChameleonLookup)
class ChameleonRendererLookup(object): class ChameleonRendererLookup(object):
spec_re = re.compile(
r'(?P<asset>[\w_.:/-]+)'
r'(?:\#(?P<defname>[\w_]+))?'
r'(\.(?P<ext>.*))'
)

def __init__(self, impl, registry): def __init__(self, impl, registry):
self.impl = impl self.impl = impl
self.registry = registry self.registry = registry
Expand Down Expand Up @@ -417,6 +423,12 @@ def auto_reload(self):
return False return False
return settings.get('reload_templates', False) return settings.get('reload_templates', False)


def _crack_spec(self, spec):
asset, macro, ext = self.spec_re.match(spec).group(
'asset', 'defname', 'ext'
)
return asset, macro, ext

def __call__(self, info): def __call__(self, info):
spec = self.get_spec(info.name, info.package) spec = self.get_spec(info.name, info.package)
registry = info.registry registry = info.registry
Expand All @@ -436,27 +448,22 @@ def __call__(self, info):
# spec is a package:relpath asset spec # spec is a package:relpath asset spec
renderer = registry.queryUtility(ITemplateRenderer, name=spec) renderer = registry.queryUtility(ITemplateRenderer, name=spec)
if renderer is None: if renderer is None:
p = re.compile( asset, macro, ext = self._crack_spec(spec)
r'(?P<asset>[\w_.:/-]+)' spec_without_macro = '%s.%s' % (asset, ext)
r'(?:\#(?P<defname>[\w_]+))?'
r'(\.(?P<ext>.*))'
)
asset, macro, ext = p.match(spec).group(
'asset', 'defname', 'ext'
)
spec = '%s.%s' % (asset, ext)
try: try:
package_name, filename = spec.split(':', 1) package_name, filename = spec_without_macro.split(':', 1)
except ValueError: # pragma: no cover except ValueError: # pragma: no cover
# somehow we were passed a relative pathname; this # somehow we were passed a relative pathname; this
# should die # should die
package_name = caller_package(4).__name__ package_name = caller_package(4).__name__
filename = spec filename = spec_without_macro
abspath = pkg_resources.resource_filename(package_name, abspath = pkg_resources.resource_filename(package_name,
filename) filename)
if not pkg_resources.resource_exists(package_name, filename): if not pkg_resources.resource_exists(package_name, filename):
raise ValueError( raise ValueError(
'Missing template asset: %s (%s)' % (spec, abspath)) 'Missing template asset: %s (%s)' % (
spec_without_macro, abspath)
)
renderer = self.impl(abspath, self, macro=macro) renderer = self.impl(abspath, self, macro=macro)
settings = info.settings settings = info.settings
if not settings.get('reload_assets'): if not settings.get('reload_assets'):
Expand Down
1 change: 1 addition & 0 deletions pyramid/tests/fixtures/withmacro.pt
@@ -1,4 +1,5 @@
<html> <html>
Outside macro
<metal:m define-macro="foo"> <metal:m define-macro="foo">
Hello! Hello!
</metal:m> </metal:m>
Expand Down
9 changes: 7 additions & 2 deletions pyramid/tests/test_chameleon_zpt.py
Expand Up @@ -132,8 +132,13 @@ def test_macro_supplied(self):
result = instance.implementation()() result = instance.implementation()()
self.assertEqual(result, '\n Hello!\n') self.assertEqual(result, '\n Hello!\n')



def test_macro_notsupplied(self):

minimal = self._getTemplatePath('withmacro.pt')
lookup = DummyLookup()
instance = self._makeOne(minimal, lookup)
result = instance.implementation()()
self.assertEqual(result,
'<html>\nOutside macro\n\n Hello!\n\n</html>\n\n')


class DummyLookup(object): class DummyLookup(object):
auto_reload=True auto_reload=True
Expand Down
7 changes: 6 additions & 1 deletion pyramid/tests/test_renderers.py
Expand Up @@ -295,17 +295,19 @@ def test___call__spec_notyetregistered(self):
self.assertEqual(factory.kw, {'macro':None}) self.assertEqual(factory.kw, {'macro':None})


def test___call__spec_withmacro(self): def test___call__spec_withmacro(self):
from pyramid.interfaces import ITemplateRenderer
import os import os
from pyramid import tests from pyramid import tests
module_name = tests.__name__ module_name = tests.__name__
relpath = 'fixtures/withmacro#foo.pt' relpath = 'fixtures/withmacro#foo.pt'
renderer = {} renderer = {}
factory = DummyFactory(renderer) factory = DummyFactory(renderer)
spec = '%s:%s' % (module_name, relpath) spec = '%s:%s' % (module_name, relpath)
reg = self.config.registry
info = DummyRendererInfo({ info = DummyRendererInfo({
'name':spec, 'name':spec,
'package':None, 'package':None,
'registry':self.config.registry, 'registry':reg,
'settings':{}, 'settings':{},
'type':'type', 'type':'type',
}) })
Expand All @@ -318,6 +320,9 @@ def test___call__spec_withmacro(self):
'withmacro.pt') 'withmacro.pt')
self.assertTrue(factory.path.startswith(path)) self.assertTrue(factory.path.startswith(path))
self.assertEqual(factory.kw, {'macro':'foo'}) self.assertEqual(factory.kw, {'macro':'foo'})
self.assertTrue(
reg.getUtility(ITemplateRenderer, name=spec) is renderer
)


def test___call__reload_assets_true(self): def test___call__reload_assets_true(self):
import pyramid.tests import pyramid.tests
Expand Down

0 comments on commit fa587ef

Please sign in to comment.