Permalink
Browse files

Merge branch 'fix.templatemacroreg'

  • Loading branch information...
2 parents 571f1b6 + fa587ef commit 9811b08518c594c24fddf86dba8f5956117fa89b @mcdonc mcdonc committed Oct 5, 2012
View
@@ -367,6 +367,12 @@ def _render(value, system):
@implementer(IChameleonLookup)
class ChameleonRendererLookup(object):
+ spec_re = re.compile(
+ r'(?P<asset>[\w_.:/-]+)'
+ r'(?:\#(?P<defname>[\w_]+))?'
+ r'(\.(?P<ext>.*))'
+ )
+
def __init__(self, impl, registry):
self.impl = impl
self.registry = registry
@@ -417,6 +423,12 @@ def auto_reload(self):
return 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):
spec = self.get_spec(info.name, info.package)
registry = info.registry
@@ -436,27 +448,22 @@ def __call__(self, info):
# spec is a package:relpath asset spec
renderer = registry.queryUtility(ITemplateRenderer, name=spec)
if renderer is None:
- p = re.compile(
- r'(?P<asset>[\w_.:/-]+)'
- r'(?:\#(?P<defname>[\w_]+))?'
- r'(\.(?P<ext>.*))'
- )
- asset, macro, ext = p.match(spec).group(
- 'asset', 'defname', 'ext'
- )
- spec = '%s.%s' % (asset, ext)
+ asset, macro, ext = self._crack_spec(spec)
+ spec_without_macro = '%s.%s' % (asset, ext)
try:
- package_name, filename = spec.split(':', 1)
+ package_name, filename = spec_without_macro.split(':', 1)
except ValueError: # pragma: no cover
# somehow we were passed a relative pathname; this
# should die
package_name = caller_package(4).__name__
- filename = spec
+ filename = spec_without_macro
abspath = pkg_resources.resource_filename(package_name,
filename)
if not pkg_resources.resource_exists(package_name, filename):
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)
settings = info.settings
if not settings.get('reload_assets'):
View
@@ -150,7 +150,8 @@ class PServeCommand(object):
_reloader_environ_key = 'PYTHON_RELOADER_SHOULD_RUN'
_monitor_environ_key = 'PASTE_MONITOR_SHOULD_RUN'
- possible_subcommands = ('start', 'stop', 'restart', 'status')
+ possible_subcommands = ('start', 'stop', 'restart', 'status',
+ 'handle_reload_error')
def __init__(self, argv, quiet=False):
self.quiet = quiet
@@ -191,6 +192,34 @@ def run(self): # pragma: no cover
install_reloader(int(self.options.reload_interval), [app_spec])
# if self.requires_config_file:
# watch_file(self.args[0])
+ if cmd == 'handle_reload_error':
+ self.out(
+ 'There was a reload error: your application did not '
+ 'start properly when restarted by the reloader. You '
+ 'will need to examine the traceback above, and fix '
+ 'the issue. The process will restart after each code '
+ 'change until the problem is fixed. In some '
+ 'circumstances (such as when there is an ImportError '
+ 'raised at module scope), changes you make to the '
+ 'offending module will not cause a restart '
+ 'and you will need to change the __init__.py '
+ 'of your application to force a reload. If that '
+ 'does not work, you will need to restart the process '
+ 'by hand.')
+ app_name = self.options.app_name
+ base = os.getcwd()
+ vars = self.parse_vars(restvars)
+ if not self._scheme_re.search(app_spec):
+ app_spec = 'config:' + app_spec
+ try: # populate sys.modules
+ app = self.loadapp(
+ app_spec, name=app_name,
+ relative_to=base, global_conf=vars)
+ except: # but ignore any exceptions
+ pass
+ while 1:
+ time.sleep(1)
+
else:
return self.restart_with_reloader()
@@ -526,8 +555,10 @@ def restart_with_monitor(self, reloader=False): # pragma: no cover
if reloader:
# Reloader always exits with code 3; but if we are
# a monitor, any exit code will restart
- if exit_code != 3:
- return exit_code
+ while exit_code != 3:
+ handle_error_args = args + ['handle_reload_error']
+ proc = subprocess.Popen(handle_error_args, env=new_environ)
+ exit_code = proc.wait()
if self.verbose > 0:
self.out('%s %s %s' % ('-' * 20, 'Restarting', '-' * 20))
@@ -1,4 +1,5 @@
<html>
+Outside macro
<metal:m define-macro="foo">
Hello!
</metal:m>
@@ -132,8 +132,13 @@ def test_macro_supplied(self):
result = instance.implementation()()
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):
auto_reload=True
@@ -295,17 +295,19 @@ def test___call__spec_notyetregistered(self):
self.assertEqual(factory.kw, {'macro':None})
def test___call__spec_withmacro(self):
+ from pyramid.interfaces import ITemplateRenderer
import os
from pyramid import tests
module_name = tests.__name__
relpath = 'fixtures/withmacro#foo.pt'
renderer = {}
factory = DummyFactory(renderer)
spec = '%s:%s' % (module_name, relpath)
+ reg = self.config.registry
info = DummyRendererInfo({
'name':spec,
'package':None,
- 'registry':self.config.registry,
+ 'registry':reg,
'settings':{},
'type':'type',
})
@@ -318,6 +320,9 @@ def test___call__spec_withmacro(self):
'withmacro.pt')
self.assertTrue(factory.path.startswith(path))
self.assertEqual(factory.kw, {'macro':'foo'})
+ self.assertTrue(
+ reg.getUtility(ITemplateRenderer, name=spec) is renderer
+ )
def test___call__reload_assets_true(self):
import pyramid.tests

0 comments on commit 9811b08

Please sign in to comment.