Package: anytemplate
AboutThis is a python library works as an abstraction layer for various python
template engines and rendering libraries, and provide a few very simple and
easily understandable APIs to render templates.Also a CLI tool called anytemplate_cli is provided to render templates written
in these template languages.Author: Satoru SATOH <ssato@redhat.com>License: MITThe following template engines are supported currently:NameNotesstring.TemplateAlways available as it’s included in python standard lib.jinja2Highest priory will be given and becomes default if foundmakotenjinrenders() API is not supportedCheetahCheetah3is needed to use with python 3.xpystacheFeaturesProvides very simple and unified APIs for various template engines:anytemplate.renders() to render given template stringanytemplate.render() to render given template fileCan process template engine specific options:anytemplate.render{s,} allow passing option parameters specific to each template rendering functions behind this libraryanytemplate.find_engine() returns an ‘engine’ object to allow some more fine tunes of template engine specific customization by passing option parameters to themProvide a CLI tool called anytemplate_cli to process templates in command lineAPI UsageAPI ExamplesCall ‘anytemplate.renders’ to render given template strings like this:result=anytemplate.renders("{{ x|default('aaa') }}",{'x':'bbb'},at_engine="jinja2")The first parameter is a template string itself. And the second one is a dict
or dict-like object which is generally called as ‘context’ object to
instantiate templates. The third one, keyword parameter ‘at_engine’ is needed
to find the appropriate template engine to render given template string. This
keyword parameter is necessary because it’s very difficult and should be almost
impossible for any template languages to detect correct template engine only by
given template string itself.If ‘at_engine’ is omitted, a template engine of highest priority is choosen.
Only available template engines and libraries are enabled automatically in
anytemplate, so that that engine will be vary in accordance with your
environment. For example, ‘jinja2’ is the engine of highest priority in my
development envrionment with all supported template engines and libraries
installed:In[6]:importanytemplateIn[7]:anytemplate.find_engine()# It will return the highest priority one.Out[7]:anytemplate.engines.jinja2.EngineIn[8]:anytemplate.find_engine().name()Out[8]:'jinja2'It’s also possible to some option parameters specific to the template engine
choosen with keyword parameters like this:# 'strict_undefined' is a parameter for mako.template.Template.__init__().result=anytemplate.renders("${x}",{'x':'bbb'},at_engine="mako",strict_undefined=False)For details such as generic option parameters list of ‘anytemplate.renders’,
see its help:In[20]:help(anytemplate.renders)Helponfunctionrendersinmoduleanytemplate.api:renders(template_content,context=None,at_paths=None,at_encoding='UTF-8',at_engine=None,at_ask_missing=False,at_cls_args=None,**kwargs)Compileandrendergiventemplatecontentandreturntheresultstring.:paramtemplate_content:Templatecontent:paramcontext:Adictordict-likeobjecttoinstantiategiventemplatefile:paramat_paths:Templatesearchpaths:paramat_encoding:Templateencoding:paramat_engine:SpecifythenameoftemplateenginetouseexplicitlyorNonetofinditautomaticallyanyhow.:paramat_cls_args:Argumentspassedtoinstantiatetemplateengineclass:paramkwargs:Keywordargumentspassedtothetemplateenginetorendertemplateswithspecificfeaturesenabled.:return:RenderedstringIn[21]:Call ‘anytemplate.render’ to render given template file like this:result1=anytemplate.render("/path/to/a_template.tmpl",{'x':'bbb'},at_engine="mako")result2=anytemplate.render("another_template.t",{'y':'ccc'},at_engine="tenjin",at_paths=['/path/to/templates/','.'])The parameters are similar to the previous example except for the first one.The first parameter is not a template string but a path of template file, may
be relative or absolute path, or basename with template search paths
(at_paths=[PATH_0, PATH_1, …]) given.Some module wraps actual template engines in anytemplate supports automatic
detection of the engine by file extensions of template files. For example,
Jinja2 template files of which expected file extensions are ‘.j2’ or ‘.jinja2’
typically. So I made that such files are automatically detected as jinja2
template file and you don’t need to specify the engine by ‘at_engine’ parameter
like this:# 'jinaj2' template engine is automatically choosen because the extension# of template file is '.j2'.result=anytemplate.render("/path/to/a_template.j2",{'x':'bbb'})For details such as option parameters list of ‘anytemplate.render’,
see its help:In[21]:help(anytemplate.render)Helponfunctionrenderinmoduleanytemplate.api:render(filepath,context=None,at_paths=None,at_encoding='UTF-8',at_engine=None,at_ask_missing=False,at_cls_args=None,**kwargs)Compileandrendergiventemplatefileandreturntheresultstring.:paramtemplate:Templatefilepath:paramcontext:Adictordict-likeobjecttoinstantiategiventemplatefile:paramat_paths:Templatesearchpaths:paramat_encoding:Templateencoding:paramat_engine:SpecifythenameoftemplateenginetouseexplicitlyorNonetofinditautomaticallyanyhow.:paramat_cls_args:Argumentspassedtoinstantiatetemplateengineclass:paramkwargs:Keywordargumentspassedtothetemplateenginetorendertemplateswithspecificfeaturesenabled.:return:RenderedstringIn[22]:CLI UsageCLI helpssato@localhost%PYTHONPATH=.pythonanytemplate/cli.py-hUsage: anytemplate/cli.py [OPTION ...] TEMPLATE_FILE

Options:
  -h, --help            show this help message and exit
  -T TEMPLATE_PATHS, --template-path=TEMPLATE_PATHS
                        Template search path can be specified multiple times.
                        Note: Dir in which given template exists is always
                        included in the search paths (at the end of the path
                        list) regardless of this option.
  -C CONTEXTS, --context=CONTEXTS
                        Specify file path and optionally its filetype, to
                        provides context data to instantiate templates.  The
                        option argument's format is
                        [type:]<file_name_or_path_or_glob_pattern> ex. -C
                        json:common.json -C ./specific.yaml -C yaml:test.dat,
                        -C yaml:/etc/foo.d/*.conf
  -E ENGINE, --engine=ENGINE
                        Specify template engine name such as 'jinja2'
  -L, --list-engines    List supported template engines in your environment
  -o OUTPUT, --output=OUTPUT
                        Output filename [stdout]
  -v, --verbose         Verbose mode
  -q, --quiet           Quiet modessato@localhost%catexamples/ctx.ymlxs:
  - name: Alice
  - name: Bob
  - name: Johnssato@localhost%catexamples/jinja2.j2{% include "jinja2-incl.j2" %}ssato@localhost%catexamples/jinja2-incl.j2{# jinja2 example: #}
{% for x in xs if x.name -%}
{{ x.name }}
{% endfor %}ssato@localhost%PYTHONPATH=.pythonanytemplate/cli.py-Ejinja2\>-Cexamples/ctx.ymlexamples/jinja2.j2Alice
Bob
Johnssato@localhost%CLI FeaturesMultiple context files support to define template parametersThe CLI tool (anytemplate_cli) supports to load multiple context files in YAML
or JSON or others to give template parameters with -C|–context option.Loading and composing of context files are handled by my another python library
called anyconfig (python-anyconfig) if installed and available on your system.anyconfig on PyPI:http://pypi.python.org/pypi/anyconfig/python-anyconfig on github:https://github.com/ssato/python-anyconfigIf anyconfig is not found on your system, only JSON context files are supported
format of context files, by help of python standard json or simplejson library.Template search pathsTemplate search paths are specified with -T|–template-path option of the CLI
tool (anytemplate_cli).  This is useful when using ‘include’ directive in
templates; ex. -T .:templates/.NOTE: The default search path will be [‘.’,
dir_in_which_given_template_file_is] where templatedir is the directory in
which the given template file exists if -T option is not given.  And even if -T
option is used, templatedir will be appended to that search paths at the end.Build & InstallIf you’re Fedora or Red Hat Enterprise Linux user, you can build and install
[s]rpm by yourself:$pythonsetup.pysrpm&&mockdist/python-anytemplate-<ver_dist>.src.rpmor:$pythonsetup.pyrpmor you can install pre-built RPMs from one of my copr repos,https://copr.fedorainfracloud.org/coprs/ssato/python-anyconfig/#Fedora$sudodnfcoprenablessato/python-anyconfig$sudodnfinstall-ypython-anytemplate# or python3-anytemplate (python3 version)#RHEL,CentOS$(cd/etc/yum.repos.d;sudocurl-Ohttps://copr.fedorainfracloud.org/coprs/ssato/python-anyconfig/repo/epel-7/ssato-python-anyconfig-epel-7.repo)$sudodnfinstall-ypython-anytemplate# or python3-anytemplate (python3 version)Otherwise, try usual ways to build and/or install python modules such like ‘pip
install git+https://github.com/ssato/python-anytemplate’ and ‘python setup.py
bdist’, etc.HackingHow to testI choose tox for manual tests and CI. Try to run ‘tox [-e py27]’ for example.TODO & IssuesAdd descriptions (doctext) of template engine and library specific options: WIPAdd descriptions (doctext) how anytemplate wraps each template engine and library: WIPComplete unit tests:Add test cases of each template engine specific options: WIPStablize public and private (internal) APIs:Private APIs still needs a lot of work especially. It’s very vague how it should be as each template engine have its own concept and design and I’m not sure how to abstract them yet.I don’t think public APIs have large issues but these be affected by changes of private APIs more or less; I’m thinking to deprecate the keyword parameter ‘at_cls_args’ for example.MiscAlternativesThere are a few libraries works like this:TemplateAlchemy:https://pypi.python.org/pypi/TemplateAlchemy/collective.templateengines:https://pypi.python.org/pypi/collective.templateenginesThese look more feature-rich and comprehensive, but I prefer a lot more
lightweight and thin wrapper library along with CLI tool (template renderer) so
that I made anytemplate.And:python-jinja2-cli:https://github.com/ssato/python-jinja2-cliAnytemplate is a successor of python-jinja2-cli.