Skip to main content

General purpose static text generator

Project description

C.W. and its contributors (See contributors.rst)





In version 0.8.0, moban.plugins.jinja2.tests.files is moved to moban-ansible package. moban.plugins.jinja2.filters.github is moved to moban-jinja2-github package Please install them for backward compatibility.

Quick start

$ export HELLO="world"
$ moban "{{HELLO}}"


$ export HELLO="world"
$ echo "{{HELLO}}" | moban

Or simply

$ HELLO="world" moban "{{HELLO}}"

A bit formal example:

$ moban -c data.yml -t my.template

Given data.yml as:

hello: world

and my.template as:


Please note that data.yml will take precedence over environment variables.

Template inheritance and custom template directories

Suppose there exists shared/base.jj2, and two templates child1.jj2 and child2.jj2 derives from it. You can do:

$ moban -t child1.jj2 -td shared -o child1
$ moban -t child2.jj2 -td shared -o child2

Data overload and custom data directories

Effectively each data file you give to moban, it overrides environment variables. Still you can have different layers of data. For example, you can have shared/company_info.yml, use project1.yml for project 1 and project2.yml for project 2. In each of the derived data file, simply mention:

overrides: company_info.yml

Here is the command line to use your data:

$ moban -cd shared -c project1.yaml -t README.jj2

Custom jinja2 extension

moban allows the injection of user preferred jinja2 extensions:

$ moban -e jj2=jinja2_time.TimeExtension ...

Well, can I nick some existing functions as filters, tests? Or create a global from another library?

Sure, you can use the same ‘-e’ syntax:

$ moban -e jinja2=filter:module.path.filter_function \
           jinja2=test:module.path.test_function \

In this case, you would have to include the external library in your own requirements.txt

Here is an example:

$ moban -e jinja2=filter:moban.externals.file_system.url_join \
  jinja2=test:moban.externals.file_system.exists \
  jinja2=global:description=moban.constants.PROGRAM_DESCRIPTION \
  -t "{{ 'a'|url_join('b')}} {{'b' is exists}}"

Can I write my own jinja2 test, filter and/or globals?

moban allows the freedom of craftsmanship. Please refer to the docs for more details. Here is an example:

import sys
import base64

from moban.plugins.jinja2.extensions import JinjaFilter

def base64encode(string):
    if sys.version_info[0] > 2:
        content = base64.b64encode(string.encode("utf-8"))
        content = content.decode("utf-8")
        content = base64.b64encode(string)
    return content

And you can use it within your jinja2 template, mytest.jj2:

{{ 'abc' | base64encode }}

Assume that the custom example was saved in custom-jj2-plugin

$ moban -pd custom-jj2-plugin -t mytest.jj2 ...

Moban will then load your custom jinja2 functions

Slim template syntax for jinja2

with moban-slim installed,

Given a data.json file with the following content

  "person": {
    "firstname": "Smith",
    "lastname": "Jones",
$ moban --template-type slim -c data.json  "{{person.firstname}} {{person.lastname}}"
Smith Jones

Handlebars.js template

With moban-handlebars installed,

Given a data.json file with the following content

  "person": {
    "firstname": "Yehuda",
    "lastname": "Katz",
$ moban --template-type handlebars -c data.json  "{{person.firstname}} {{person.lastname}}"
Yehuda Katz

For handlebars.js users, yes, the example was copied from The aim is to show off what we can do.

Let’s continue with a bit more fancy feature:

$ moban --template-type handlebars -c data.json "{{#with person}}{{firstname}} {{lastname}} {{/with}}"

Moban’s way of pybar3 usage:

Let’s save the following file a under helper_and_partial folder:

from moban_handlebars.api import Helper, register_partial

register_partial('header', '<h1>People</h1>')

def _list(this, options, items):
    result = [u'<ul>']
    for thing in items:
    return result

And given data.json reads as the following:

        {"name": "Bill", "age": 100},
        {"name": "Bob", "age": 90},
        {"name": "Mark", "age": 25}

Let’s invoke handlebar template:

$ moban --template-type hbs -pd helper_and_partial -c data.json "{{>header}}{{#list people}}{{name}} {{age}}{{/list}}"
Handlebars-ing {{>header}... to moban.output
Handlebarsed 1 file.
$ cat moban.output
<h1>People</h1><ul><li>Bill 100</li><li>Bob 90</li><li>Mark 25</li></ul>

Velocity template

With moban-velocity installed,

Given the following data.json:

        {"name": "Bill", "age": 100},
        {"name": "Bob", "age": 90},
        {"name": "Mark", "age": 25}

And given the following velocity.template:

Old people:
#foreach ($person in $people)
 #if($person.age > 70)

Third person is $people[2].name

moban can do the template:

$ moban --template-type velocity -c data.json -t velocity.template
Old people:



Third person is Mark

Can I write my own template engine?

Yes and please check for more details.

Given the following template type function, and saved in custom-plugin dir:

from moban.core.content_processor import ContentProcessor

@ContentProcessor("de-duplicate", "De-duplicating", "De-duplicated")
def de_duplicate(content: str, options: dict) -> str:
    lines = content.split(b'\n')
    new_lines = []
    for line in lines:
        if line not in new_lines:
    return b'\n'.join(new_lines)

You can start using it like this:

$ moban --template-type de-duplicate -pd custom-plugin -t duplicated_content.txt

TOML data format

moban-anyconfig should be installed first.

Given the following toml file, sample.toml:

title = "TOML Example"
name = "Tom Preston-Werner"

You can do:

$ moban -c sample.toml "{{}} made {{title}}"
Tom Preston-Werner made TOML Example

Not limited to toml, you can supply moban with the following data formats:

Always supported formats, quoting from python-anyconfig






json (standard lib) or simplejson



configparser (standard lib)



pickle (standard lib)



ElementTree (standard lib)

Java properties


None (native implementation with standard lib)



None (native implementation with standard lib)

For any of the following data formats, you elect to install by yourself.

Supported formats by pluggable backend modules



Required backend

Amazon Ion








anyconfig-cbor-backend or anyconfig-cbor2-backend







Or you could choose to install all:

$ pip install moban-anyconfig[all-backends]

Why not to use python-anyconfig itself, but yet another package?

moban gives you a promise of any location which python-anyconfig does not support.

Why do it mean ‘any location’?

Thanks to pyfilesystem 2, moban is able to read data back from git repo, pypi package, http(s), zip, tar, ftp, s3 or you name it.

Templates and configuration files over HTTP(S)

httpfs should be installed first.

With httpfs, moban can access any files over http(s) as its template or data file:

$ moban -t ''\
  -c ''\

In an edge case, if github repo’s public url is given, this github repo shall not have sub repos. This library will fail to translate sub-repo as url. No magic.

Templates and configuration files in a git repo

gitfs2 is optional since v0.7.0 but was installed by default since v0.6.1

You can do the following with moban:

$ moban -t 'git://!/templates/' \
        -c 'git://!/config/data.yml' \
Info: Found repo in /Users/jaska/Library/Caches/gitfs2/repos/pypi-mobans
Templating git://!/templates/ to
Templated 1 file.
$ cat
__version__ = "0.1.1rc3"
__author__ = "C.W."

Templates and configuration files in a python package

pypifs is optional since v0.7.0 but was installed by default since v0.6.1

You can do the following with moban:

$ moban -t 'pypi://pypi-mobans-pkg/resources/templates/' \
        -c 'pypi://pypi-mobans-pkg/resources/config/data.yml' \
Collecting pypi-mobans-pkg
Installing collected packages: pypi-mobans-pkg
Successfully installed pypi-mobans-pkg-0.0.7
Templating pypi://pypi-mobans-pkg/resources/templates/ to
Templated 1 file.
$ cat
__version__ = "0.1.1rc3"
__author__ = "C.W."

Work with S3 and other cloud based file systems

Please install fs-s3fs:

$ pip install fs-s3fs

Then you can access your files in s3 bucket:

$ moban -c s3://${client_id}:${client_secrect}@moremoban/s3data.yml \
        -o 'zip://!/moban.output' {{hello}}
$ unzip
$ cat moban.output

Where the configuration sits in a s3 bucket, the output is a file in a zip. The content of s3data.yaml is:

So what can I do with it

Here is a list of other usages:

  1. Django Mobans, templates for django, docker etc.

  2. Math Sheets, generate custom math sheets in pdf

At scale, continous templating for open source projects

moban enabled continuous templating in pyexcel and coala project to keep documentation consistent across the documentations of individual libraries in the same organisation. Here is the primary use case of moban, as of now:

Usage beyond command line

All use cases are documented


If you like moban, please support me on github, patreon or bounty source to maintain the project and develop it further.

With your financial support, I will be able to invest a little bit more time in coding, documentation and writing interesting extensions.


Any template, any data in any location

moban started with bringing the high performance template engine (JINJA2) for web into static text generation.

moban can use other python template engine: mako, handlebars, velocity, haml, slim and tornado, can read other data format: json and yaml, and can access both template file and configuration file in any location: zip, git, pypi package, s3, etc.


jinja2-fsloader is the key component to enable PyFilesystem2 support in moban v0.6x. Please show your stars there too!


You can install it via pip:

$ pip install moban

or clone it and install it:

$ git clone
$ cd moban
$ python install

CLI documentation

usage: moban [-h] [-c CONFIGURATION] [-t TEMPLATE] [-o OUTPUT]
             [-td [TEMPLATE_DIR [TEMPLATE_DIR ...]]]
             [-pd [PLUGIN_DIR [PLUGIN_DIR ...]]] [-cd CONFIGURATION_DIR]
             [-m MOBANFILE] [-g GROUP] [--template-type TEMPLATE_TYPE]
             [-d DEFINE [DEFINE ...]] [-e EXTENSION [EXTENSION ...]] [-f]
             [--exit-code] [-V] [-v]

Static text generator using any template, any data and any location.

positional arguments:
  template              string templates

optional arguments:
  -h, --help            show this help message and exit
                        the data file
  -t TEMPLATE, --template TEMPLATE
                        the template file
  -o OUTPUT, --output OUTPUT
                        the output file

Advanced options:
  For better control

  -td [TEMPLATE_DIR [TEMPLATE_DIR ...]], --template_dir [TEMPLATE_DIR [TEMPLATE_DIR ...]]
                        add more directories for template file lookup
                        the directory for configuration file lookup
  -pd [PLUGIN_DIR [PLUGIN_DIR ...]], --plugin_dir [PLUGIN_DIR [PLUGIN_DIR ...]]
                        add more directories for plugin lookup
  -m MOBANFILE, --mobanfile MOBANFILE
                        custom moban file
  -g GROUP, --group GROUP
                        a subset of targets
  --template-type TEMPLATE_TYPE
                        the template type, default is jinja2
  -d DEFINE [DEFINE ...], --define DEFINE [DEFINE ...]
                        to supply additional or override predefined variables,
                        format: VAR=VALUEs
                        to to TEMPLATE_TYPE=EXTENSION_NAME
  -f                    force moban to template all files despite of

Developer options:
  For debugging and development

  --exit-code           by default, exist code 0 means no error, 1 means error
                        occured. It tells moban to change 1 for changes, 2 for
                        error occured
  -V, --version         show program's version number and exit
  -v                    show verbose, try -v, -vv, -vvv

8 contributors

In alphabetical order:

Change log

0.8.2 - 04.09.2020


  1. Use any functions, any data structure of any python packages as jinja2 filters, tests, globals

0.8.1 - 04.09.2020


  1. #399: content processor should be called only once

  2. content processor shall pass on options to content processors

0.8.0 - 02.09.2020


  1. moban.plugins.jinja2.tests.files is moved to moban-ansible package

  2. moban.plugins.jinja2.filters.github is moved to moban-jinja2-github package


  1. #396: custom jinja2 plugins(filters, tests and globals) are not visible if a template is passed as a string.

0.7.10 - 16.08.2020


  1. #393: Rendered content output to stdout once

0.7.9 - 06.08.2020


  1. #390: single render action will print to stdout by default

0.7.8 - 09.06.2020


  1. #313: Non-textual source files should default to copy

0.7.7 - 24.5.2020


  1. -pd for command line to include custom plugin directories


  1. strip did not work in 0.7.6

0.7.6 - 22.5.2020


  1. #38: finally be able strip the rendered content

0.7.5 - 21.5.2020


  1. #167: reverse what moban have done: delete

0.7.4 - 13.5.2020


  1. #378: suppress stdout message from deprecated pip install. but please do not use and migrate deprecated`requires` syntax.

0.7.3 - 2.5.2020


  1. Added continuous check in travis for descriptions. No impact to moban user.

0.7.2 - 1.5.2020


  1. Support for templates and configuration files over HTTP(S) protocol with httpfs! Yepee!

0.7.1 - 25.04.2020


  1. #365: regression was introduced by v0.6.5. If you uses mobanfile as data configuration file, you are very likely to have this show stopper. Please upgrade to this version.

0.7.0 - 18.01.2020


  1. #360: make gitfs2 and pypifs optional.

  2. #303: python 2.7 support is dropped.


  1. #360: show friendlier error when unknown protocol exception was raised.

0.6.8 - 7.12.2019


  1. since version 0.5.0, when rendering a single file or string, moban would report ‘Templated 1 of 0 files’, which should have been ‘Templated 1 file.’


  1. python 3.4 support is gone because colorama requires Python ‘>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*’

0.6.7 - 1.12.2019


  1. no verbose for error, -v for warning, -vv for warning+info, -vvv for warning+info+debug

  2. #351, show template plugin name, i.e. ‘copying’ for copy instead of ‘templating’


  1. Message: ‘Warning: Attempting to use environment vars as data…’ became warning log

  2. Message: ‘Warning: Both data.yml and /…/ does not exist’ became warning log

  3. with -v, you would see them in such a situation

0.6.6 - 10.11.2019


  1. support moban file inheritance. one base moban file and child repos can inherit and override

0.6.5 - 13.10.2019


  1. #335: support intermediate targets in moban file

0.6.4 - 4.10.2019


  1. Command options have been grouped. –template_type became –template-type

  2. Increment gitfs2 to version 0.0.2. gitfs#4

0.6.3 - 25.09.2019


  1. #260: jinja-cli parity: support command line pipe stream.

0.6.2 - 15.09.2019


  1. #322: Implicit targets with template extensions default to copy

  2. #257: ‘-e’ to load extensions for template engines, i.e. jinja2

  3. #333: command line template fails with version 0.6.1

0.6.1 - 10.09.2019


  1. #328: update backward compatibility

0.6.0 - 10.09.2019


  1. #205: support pyFilesystem2

  2. #185: -v will enable moban application logging for development. And -V is for version.

  3. #325: -vv show debug trace

  4. #126: Allow mobanfile to include data from arbitrary config files

  5. #256: jinja2-cli parity: ‘-d hello=world’ to define custom variable on cli


  1. #275: fix moban 0.4.5 test failures on openSUSE Tumbleweed

0.5.0 - 14.07.2019


  1. #277: Restored dependency git-url-parse, replacing incompatible giturlparse which was used during moban 0.4.x

  2. #281: Fixed unicode support on Python 2.7

  3. #274: Updated ruamel.yaml dependency pins to restore support for Python 3.4, and prevent installation of versions that can not be installed on Python 3.7

  4. #285: Fixed CI testing of minimum requirements

  5. #271: Fixed repository caching bug preventing branch switching

  6. #292: Reformatted YAML files according to yamllint rules

  7. #291: Fixed filename typos in README

  8. #280: Added CI to ensure repository is in sync with upstream

  9. #280: sync from pypi-mobans

0.4.5 - 07.07.2019


  1. #271: support git branch change in later run.

0.4.4 - 26.05.2019


  1. #265: Use simple read binary to read instead of encoding

0.4.3 - 16.03.2019


  1. #253: symbolic link in regression pack causes python to do recursive include


  1. #209: Alert moban user when git is not available and is used.


  1. #261: since moban group template files per template type, this fill use first come first register to order moban group

0.4.2 - 08.03.2019


  1. #234: Define template parameters on the fly inside targets section

  2. #62: select a group target to run


  1. #180: No longer two statistics will be shown in v0.4.x. legacy copy targets are injected into a normal targets. cli target is made a clear priority.

  2. #244: version 0.4.2 is first version which would work perfectly on windows since 17 Nov 2018. Note that: file permissions are not used on windows. Why the date? because samefile is not avaiable on windows, causing unit tests to fail hence it lead to my conclusion that moban version between 17 Nov 2018 and March 2019 wont work well on Windows.

0.4.1 - 28.02.2019


  1. #235: user defined template types so that custom file extensions, template configurations can be controlled by moban user

  2. #232: the package dependencies have been fine tuning to lower versions, most of them are dated back to 2017.

0.4.0 - 20.02.2019


  1. #165: Copy as plugins


  1. #219: git clone depth set to 2

  2. #186: lowest dependecy on ruamel.yaml is 0.15.5, Jun 2017

0.3.10 - 03.02.2019


  1. #174: Store git cache in XDG_CACHE_DIR

  2. #107: Add -v to show current moban version

  3. #164: support additional data formats


  1. #178: UnboundLocalError: local variable ‘target’ referenced before assignment

  2. #169: uses GitPython instead of barebone git commands

0.3.9 - 18-1-2019


  1. #90: allow adding extra jinja2 extensions., jinja2.ext.loopcontrols are included by default. what’s more, any other template enigne are eligible for extension additions.

  2. #158: Empty file is finally removed

0.3.8 - 12-1-2019


  1. #141: disable file permissions copy feature and not to check file permission changes on windows.

  2. #154: introduce first ever positional argument for string base template.

  3. #157: the exit code behavior changed. for backward compactibility please use –exit-code. Otherwise, moban will not tell if there is any changes.

0.3.7 - 6-1-2019


  1. #146: added a low-setup usage mode via environment variables to moban

  2. #148: include test related files in the package for package validation when distributing via linux system, i.e. OpenSuse

0.3.6 - 30-12-2018


  1. #143: moban shall report permission error and continue the rest of the copying task.

  2. #122: Since 0.3.6, moban is tested on windows and macos too, using azure build pipelines. It is already tested extensively on travis-ci on linux os.

0.3.5 - 10-12-2018


  1. #37: moban will report line number where the value is empty and the name of mobanfile. Switch from pyyaml to ruamel.yaml. - 28-11-2018


  1. #137: missing contributors.rst file

0.3.4 - 18-11-2018


  1. global variables to store the target and template file names in the jinja2 engine

  2. moban-handlebars is tested to work well with this version and above


  1. Template engine interface has been clarified and documented

0.3.3 - 05-11-2018


  1. alternative and expanded syntax for requires, so as to accomendate github submodule recursive

0.3.2 - 04-11-2018


  1. configuration dirs may be located by requires, i.e. configuration files may be in a python package or git repository.

0.3.1 - 02-11-2018


  1. #97: requires will clone a repo if given. Note: only github, gitlab, bitbucket for now

0.3.0 - 27-18-2018


  1. #89: Install pypi-hosted mobans through requires syntax


  1. #96: Fix for FileNotFoundError for plugins

  2. various documentation updates


  1. #88: removed python 2.6 support

  2. removed python 3.3 support

0.2.4 - 14-07-2018


  1. #32: option 1 copy a directory without its subdirectories.

  2. #30: command line template option is ignore when a moban file is present

0.2.3 - 10-07-2018


  1. #76: running moban as a module from python command

  2. #32: copy a directory recusively

  3. #33: template all files in a directory

0.2.2 - 16-06-2018


  1. #31: create directory if missing during copying


  1. #28: if a template has been copied once before, it is skipped in the next moban call

0.2.1 - 13-06-2018


  1. templates using the same template engine will be templated as a group

  2. update lml dependency to 0.0.3

0.2.0 - 11-06-2018


  1. #18: file exists test

  2. #23: custom jinja plugins

  3. #26: repr filter

  4. #47: allow the expansion of template engine

  5. #58: allow template type per template


  1. #34: fix plural message if single file is processed

0.1.4 - 29-May-2018


  1. #21: targets become optional

  2. #19: transfer symlink’s target file’s file permission under unix/linux systems

  3. #16: introduce copy key word in mobanfile

0.1.3 - 12-Mar-2018


  1. handle unicode on python 2

0.1.2 - 10-Jan-2018


  1. #13: strip off new lines in the templated file

0.1.1 - 08-Jan-2018


  1. the ability to present a long text as multi-line paragraph with a custom upper limit

  2. speical filter expand github references: pull request and issues

  3. #15: fix templating syntax to enable python 2.6

0.1.0 - 19-Dec-2017


  1. #14, provide shell exit code

0.0.9 - 24-Nov-2017


  1. #11, recognize .moban.yaml as well as .moban.yml.

  2. #9, preserve file permissions of the source template.

  3. -m option is added to allow you to specify a custom moban file. kinda related to issue 11.


  1. use explicit version name: moban_file_spec_version so that version can be used by users. #10 Please note: moban_file_spec_version is reserved for future file spec upgrade. For now, all files are assumed to be ‘1.0’. When there comes a new version i.e. 2.0, new moban file based on 2.0 will have to include ‘moban_file_spec_version: 2.0’

0.0.8 - 18-Nov-2017


  1. #8, verify the existence of custom template and configuration directories. default, are ignored if they do not exist.


  1. Colorize error messages and processing messages. crayons become a dependency.

0.0.7 - 19-Jul-2017


  1. Bring the visibility of environment variable into jinja2 templating process: #7

0.0.6 - 16-Jun-2017


  1. added ‘-f’ flag to force moban to template all files despite of .moban.hashes


  1. moban will not template target file in the situation where the changes occured in target file than in the source: the template file + the data configuration after moban has been applied. This new release will remove the change during mobanization process.

0.0.5 - 17-Mar-2017


  1. Create a default hash store when processing a moban file. It will save unnecessary file write to the disc if the rendered content is not changed.

  2. Added summary reports

0.0.4 - 11-May-2016


  1. Bug fix #5, should detect duplicated targets in .moban.yml file.

0.0.3 - 09-May-2016


  1. Bug fix #4, keep trailing new lines

0.0.2 - 27-Apr-2016


  1. Bug fix #1, failed to save utf-8 characters

0.0.1 - 23-Mar-2016


  1. Initial release

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

moban-0.8.2.tar.gz (1.0 MB view hashes)

Uploaded source

Built Distribution

moban-0.8.2-py2.py3-none-any.whl (46.5 kB view hashes)

Uploaded py2 py3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page