Merge branch 'fix.templatemacroreg'
| | |
| | | |
| | | @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 |
| | |
| | | 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 |
| | |
| | | # 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'): |
| | |
| | | _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 |
| | |
| | | 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() |
| | | |
| | |
| | | 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)) |
| | | |
| | |
| | | <html> |
| | | Outside macro |
| | | <metal:m define-macro="foo"> |
| | | Hello! |
| | | </metal:m> |
| | |
| | | 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 |
| | |
| | | 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__ |
| | |
| | | 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', |
| | | }) |
| | |
| | | '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 |