Source code for fireblog.theme

'''
Code that allows for changing the template files used at runtime. This
provides support for themes, which are just folders containing template files.
'''
from fireblog.settings import settings_dict
from pyramid.response import Response
from pyramid.httpexceptions import HTTPException
from pyramid import renderers
import functools
import logging


log = logging.getLogger(__name__)


[docs]class TemplateResponseDict(dict): '''Instances of this dict can be used as the return type of a view callable that is using the use_template decorator. The :py:func:`use_template` decorator will notice that an instance of this type is being returned and render it to a response. This class is used in tandem with :py:func:`template_response_adapter`''' pass
[docs]def use_template(template: str=None): """This decorator allows a view to be rendered using whatever the current active template aka theme is.""" def wrapper(f, template=template): @functools.wraps(f) def inner(context, request): res = f(context, request) # Deal with eg HTTPFound or HTTPNotFound by just returning them. if isinstance(res, HTTPException): return res # Pull out the custom dict object set by # :py:func:`fireblog.template_response_adapter` to_render = res._fireblog_custom_response if not isinstance(to_render, dict): raise Exception( # pragma: no cover "The use_template decorator is being used " "incorrectly: the decorated view callable must return a " "dict.") return render_to_response(template, to_render, request) return inner return wrapper
[docs]def render_to_response(template, res, request): theme = settings_dict['fireblog.theme'] template = 'fireblog:templates/' + theme + '/' + template log.debug('Rendering template {}'.format(template)) return renderers.render_to_response(template, res, request)
[docs]def template_response_adapter(s: TemplateResponseDict): """This function works in tandem with :py:class:`TemplateResponseDict`. This function assumes s is an instance of :py:func:`TemplateResponseDict` and returns a :py:class:`pyramid.response.Response` containing a string representation of s.""" assert isinstance(s, TemplateResponseDict) # We need to return a Response() object, as per the Pyramid specs. But we # want to not store a string in the Response yet, but an arbitrary dict # as after this function returns, :py:func:`use_template` will do further # processing on this arbitrary dict. So we set a custom field on this # Respnse object, which we can retrieve in :py:func:`use_template`. response = Response() response._fireblog_custom_response = s return response
[docs]def includeme(config): config.add_response_adapter( template_response_adapter, TemplateResponseDict)