Skip to content

Instantly share code, notes, and snippets.

@href
Created December 7, 2014 12:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save href/00cabf7fe4d35f694879 to your computer and use it in GitHub Desktop.
Save href/00cabf7fe4d35f694879 to your computer and use it in GitHub Desktop.
A Stab at Chameleon Integration in Morepath
import inspect
import morepath
import os
class ChameleonApp(morepath.App):
@morepath.reify
def chameleon_template_paths(self):
""" Returns *absolute* paths to chameleon templates.
The expected result is an iterable with one absolute path string per
iteration, i.e. a list of directories. The directories are searched in
order for the name of the template.
Alternatively, a morepath app inheriting from ChameleonApp may be
returned, which will result in the paths of that application being
expanded.
This is useful if one app with templates should be considered for
the template lookup. For examle::
@MyApp.setting(section='chameleon', name='search_paths')
def get_search_paths():
return ['templates']
Will be expanded to::
[
'path to MyAppClass/templates'
]
And::
@MyDifferentApp.setting(section='chameleon', name='search_paths')
def get_search_paths():
return ['templates', MyApp]
Will be expanded to:
[
'path to MyDifferentClass/templates',
'path to MyAppClass/templates'
]
"""
def expand_paths(paths):
for ix, item in enumerate(paths):
# if the returned item is
if inspect.isclass(item):
for path in item().chameleon_template_paths:
yield path
elif not item.startswith('/'):
yield os.path.join(
os.path.dirname(inspect.getfile(self.__class__)), item)
else:
yield item
return list(
expand_paths(self.registry.settings.chameleon.search_paths))
@morepath.reify
def chameleon_templates(self):
""" Returns an instanace of the chameleon.PageTemplateLoader with
the template paths set to `chameleon_template_paths`
"""
if self.registry.settings.chameleon.auto_reload:
# this will result in a warning from chameleon at the moment:
# https://github.com/malthe/chameleon/issues/183
os.environ['CHAMELEON_RELOAD'] = 'true'
# Only import after setting the environment variable, or it won't
# be recognized.
import chameleon
return chameleon.PageTemplateLoader(self.chameleon_template_paths)
@ChameleonApp.setting(section="chameleon", name="search_paths")
def get_search_paths():
""" Returns the chameleon search paths for the app. """
raise NotImplementedError
@ChameleonApp.setting(section="chameleon", name="auto_reload")
def get_debug():
""" Returns True if the template files should be automatically reloaded.
"""
# TODO configure this for deployment
return True
def render_chameleon(content, request):
""" Renders the content with a chameleon template.
The content is a dictionary of template variables used in the template.
"""
template = request.app.chameleon_templates[content.pop('template')]
rendered = template(**content)
return morepath.request.Response(rendered, content_type='text/html')
@ChameleonApp.directive('chameleon')
class ChameleonDirective(morepath.directive.ViewDirective):
""" Chameleon template view directive. Use like a morepath view::
@MyApp.chameleon(model=Root, path='')
def root(self, request, form=None):
return {
'template': 'blogpost.pt',
'title': 'My Blog Post'
}
"""
def __init__(self, app, model, render=None, permission=None,
internal=False, **predicates):
""" Register Chameleon view. """
render = render or render_chameleon
super(ChameleonDirective, self).__init__(
app, model, render, permission, internal, **predicates)
def group_key(self):
return morepath.directive.ViewDirective
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment