diff options
| author | Chris McDonough <chrism@plope.com> | 2012-10-05 14:24:37 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2012-10-05 14:24:37 -0400 |
| commit | 9811b08518c594c24fddf86dba8f5956117fa89b (patch) | |
| tree | d8b2477e5ef5d980692e01cebf15875aae8d88be | |
| parent | 571f1b6836bec084feec70ccf1e0fb8ced0af317 (diff) | |
| parent | fa587efc26c285cdc7e23990f947fdbd233ab53a (diff) | |
| download | pyramid-9811b08518c594c24fddf86dba8f5956117fa89b.tar.gz pyramid-9811b08518c594c24fddf86dba8f5956117fa89b.tar.bz2 pyramid-9811b08518c594c24fddf86dba8f5956117fa89b.zip | |
Merge branch 'fix.templatemacroreg'
| -rw-r--r-- | pyramid/renderers.py | 31 | ||||
| -rw-r--r-- | pyramid/scripts/pserve.py | 37 | ||||
| -rw-r--r-- | pyramid/tests/fixtures/withmacro.pt | 1 | ||||
| -rw-r--r-- | pyramid/tests/test_chameleon_zpt.py | 9 | ||||
| -rw-r--r-- | pyramid/tests/test_renderers.py | 7 |
5 files changed, 67 insertions, 18 deletions
diff --git a/pyramid/renderers.py b/pyramid/renderers.py index 1368e190e..57a61ebba 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -367,6 +367,12 @@ class JSONP(JSON): @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 @@ class ChameleonRendererLookup(object): 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 @@ class ChameleonRendererLookup(object): # 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'): diff --git a/pyramid/scripts/pserve.py b/pyramid/scripts/pserve.py index 9fbf0729a..533f708fc 100644 --- a/pyramid/scripts/pserve.py +++ b/pyramid/scripts/pserve.py @@ -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 @@ class PServeCommand(object): 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 @@ class PServeCommand(object): 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)) diff --git a/pyramid/tests/fixtures/withmacro.pt b/pyramid/tests/fixtures/withmacro.pt index 8bca01e4d..6fa654645 100644 --- a/pyramid/tests/fixtures/withmacro.pt +++ b/pyramid/tests/fixtures/withmacro.pt @@ -1,4 +1,5 @@ <html> +Outside macro <metal:m define-macro="foo"> Hello! </metal:m> diff --git a/pyramid/tests/test_chameleon_zpt.py b/pyramid/tests/test_chameleon_zpt.py index 37538e83e..5ac57f869 100644 --- a/pyramid/tests/test_chameleon_zpt.py +++ b/pyramid/tests/test_chameleon_zpt.py @@ -132,8 +132,13 @@ class ZPTTemplateRendererTests(Base, unittest.TestCase): 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 diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py index af9188abc..cb6c364a7 100644 --- a/pyramid/tests/test_renderers.py +++ b/pyramid/tests/test_renderers.py @@ -295,6 +295,7 @@ class TestChameleonRendererLookup(unittest.TestCase): 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__ @@ -302,10 +303,11 @@ class TestChameleonRendererLookup(unittest.TestCase): 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 @@ class TestChameleonRendererLookup(unittest.TestCase): '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 |
