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