Skip to content

Commit

Permalink
Initial prototype for 202 template types (moremoban#239)
Browse files Browse the repository at this point in the history
* 🔨 code refactoring

* 💄 reformat code

* 🔥 remove MobanEngine's reference to the engine class

* 🔨 refactoring the code and un-bury engine instance

* ✨ initial prototype, not tested. moremoban#235

* 📚 fix doc build

* 🐛 fix docs build

* 🔨 refactoring. user define template takes precedence

* 🔬 test user define engine

* ✨ associate user defined file extensions with user defined template engine name, i.e. custom_jinja for jinja2, custom_handlebars for handlebars, moremoban#235

* ✨ take template types from moban file. related to moremoban#233

* 🔨 address the feedback

* 🐛 fix typos and add line feed

* 💄 beautify the code
  • Loading branch information
chfw authored and ayan-b committed Apr 21, 2019
1 parent 2cc7b42 commit f3689d8
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 20 deletions.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@
intersphinx_mapping.update({
})

master_doc = "index"
master_doc = "index"
5 changes: 5 additions & 0 deletions moban/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
LABEL_SOURCE = "source"
LABEL_DEST = "destination"
LABEL_FORCE_TEMPLATE_TYPE = "force_template_type"
LABEL_TEMPLATE_TYPES = "template_types"

# error messages
ERROR_DATA_FILE_NOT_FOUND = "Both %s and %s does not exist"
Expand Down Expand Up @@ -98,6 +99,10 @@
PYPI_PACKAGE_NAME = "name"
REQUIRE_TYPE = "type"

# Template types
TEMPLATE_TYPES_BASE_TYPE = "base_type"
TEMPLATE_TYPES_OPTIONS = "options"
TEMPLATE_TYPES_FILE_EXTENSIONS = "file_extensions"

# Extension
JINJA_FILTER_EXTENSION = "jinja_filter"
Expand Down
15 changes: 10 additions & 5 deletions moban/jinja2/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __init__(self):
constants.TEMPLATE_ENGINE_EXTENSION, tags=["jinja2", "jinja", "jj2", "j2"]
)
class Engine(object):
def __init__(self, template_dirs, extensions=None):
def __init__(self, template_dirs, options=None):
"""
Contruct a jinja2 template engine
Expand All @@ -73,10 +73,15 @@ def __init__(self, template_dirs, extensions=None):
extension for extension in JINJA2_THIRD_PARTY_EXTENSIONS
], # get a copy of this global variable
)
if is_extension_list_valid(extensions):
# because it is modified here
env_params["extensions"] += extensions
import_module_of_extension(extensions)
if options:
if "extensions" in options:
extensions = options.pop("extensions")
if is_extension_list_valid(extensions):
# because it is modified here
env_params["extensions"] += extensions
import_module_of_extension(extensions)

env_params.update(options)
self.jj2_environment = Environment(**env_params)
for filter_name, filter_function in FILTERS.get_all():
self.jj2_environment.filters[filter_name] = filter_function
Expand Down
6 changes: 6 additions & 0 deletions moban/mobanfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ def handle_moban_file_v1(moban_file_configurations, command_line_options):
if extensions:
plugins.ENGINES.register_extensions(extensions)

template_types = moban_file_configurations.get(
constants.LABEL_TEMPLATE_TYPES
)
if template_types:
plugins.ENGINES.register_options(template_types)

if targets:
if target:
targets = target
Expand Down
39 changes: 28 additions & 11 deletions moban/plugins/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,52 @@ class MobanFactory(PluginManager):
def __init__(self):
super(MobanFactory, self).__init__(constants.TEMPLATE_ENGINE_EXTENSION)
self.extensions = {}
self.options_registry = {}

def register_extensions(self, extensions):
self.extensions.update(extensions)

def register_options(self, template_types):
# need the value of 'template_types'
# see test_get_user_defined_engine for help
self.options_registry.update(template_types)

def get_engine(self, template_type, template_dirs, context_dirs):
engine_cls = self.load_me_now(template_type)
engine_extensions = self.extensions.get(template_type)
return MobanEngine(
template_dirs, context_dirs, engine_cls, engine_extensions
)
if template_type in self.options_registry:
custom_engine_spec = self.options_registry[template_type]
engine_cls = self.load_me_now(
custom_engine_spec[constants.TEMPLATE_TYPES_BASE_TYPE]
)
options = custom_engine_spec[constants.TEMPLATE_TYPES_OPTIONS]
else:
engine_cls = self.load_me_now(template_type)
engine_extensions = self.extensions.get(template_type)
options = dict(extensions=engine_extensions)
engine = engine_cls(template_dirs, options)
return MobanEngine(template_dirs, context_dirs, engine)

def get_primary_key(self, template_type):
for key, item in self.options_registry.items():
if template_type in item[constants.TEMPLATE_TYPES_FILE_EXTENSIONS]:
return key

return super(MobanFactory, self).get_primary_key(template_type)

def all_types(self):
return list(self.registry.keys())
return list(self.registry.keys()) + list(self.options_registry.keys())

def raise_exception(self, key):
raise exceptions.NoThirdPartyEngine(key)


class MobanEngine(object):
def __init__(
self, template_dirs, context_dirs, engine_cls, engine_extensions=None
):
def __init__(self, template_dirs, context_dirs, engine):
template_dirs = list(expand_template_directories(template_dirs))
utils.verify_the_existence_of_directories(template_dirs)
context_dirs = expand_template_directory(context_dirs)
self.context = Context(context_dirs)
self.template_dirs = template_dirs
self.engine = engine_cls(self.template_dirs, engine_extensions)
self.engine_cls = engine_cls
self.engine = engine
self.templated_count = 0
self.file_count = 0

Expand Down
10 changes: 10 additions & 0 deletions tests/fixtures/mobanengine/sample_template_type.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
template_types:
custom_jinja:
base_type: jinja2 # use base_type, instead of overrides
file_extensions:
- moban
- new
- demo_file_suffix
options:
extensions:
- jinja2.ext.do
4 changes: 2 additions & 2 deletions tests/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def test_expand_repo_dir(_, __):

def test_default_template_type():
engine = ENGINES.get_engine("jj2", [], "")
assert engine.engine_cls == Engine
assert engine.engine.__class__ == Engine


class FakeEngine:
Expand All @@ -53,7 +53,7 @@ def __init__(self, template_dirs, extensions=None):
@patch("lml.plugin.PluginManager.load_me_now", return_value=FakeEngine)
def test_default_mako_type(_): # fake mako
engine = ENGINES.get_engine("fake", [], "")
assert engine.engine_cls.__name__ == "FakeEngine"
assert engine.engine.__class__ == FakeEngine


@raises(exceptions.NoThirdPartyEngine)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_jinja2_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def test_globals():
test_dict = dict(hello="world")
jinja_global("test", test_dict)
path = os.path.join("tests", "fixtures", "globals")
engine = MobanEngine([path], path, Engine)
engine = MobanEngine([path], path, Engine([path]))
engine.render_to_file("basic.template", "basic.yml", output)
with open(output, "r") as output_file:
content = output_file.read()
Expand Down
33 changes: 33 additions & 0 deletions tests/test_template.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import os

from mock import patch
from nose.tools import eq_

from moban.plugins import ENGINES
from moban.definitions import TemplateTarget
from moban.jinja2.engine import Engine
from moban.data_loaders.yaml import open_yaml

MODULE = "moban.plugins.template"

Expand Down Expand Up @@ -80,3 +83,33 @@ def test_do_templates_with_more_shared_data():
content = f.read()
assert content == "hello world ox"
os.unlink("test")


def test_get_user_defined_engine():
test_fixture = os.path.join(
"tests", "fixtures", "mobanengine", "sample_template_type.yml"
)
template_types = open_yaml(test_fixture)
ENGINES.register_options(template_types["template_types"])
engine = ENGINES.get_engine("custom_jinja", ".", ".")
eq_(engine.engine.__class__, Engine)


def test_custom_file_extension_is_assocated_with_user_defined_engine():
test_fixture = os.path.join(
"tests", "fixtures", "mobanengine", "sample_template_type.yml"
)
template_types = open_yaml(test_fixture)
ENGINES.register_options(template_types["template_types"])
template_type = ENGINES.get_primary_key("demo_file_suffix")
eq_("custom_jinja", template_type)


def test_built_in_jinja2_file_extension_still_works():
test_fixture = os.path.join(
"tests", "fixtures", "mobanengine", "sample_template_type.yml"
)
template_types = open_yaml(test_fixture)
ENGINES.register_options(template_types["template_types"])
template_type = ENGINES.get_primary_key("jj2")
eq_("jinja2", template_type)

0 comments on commit f3689d8

Please sign in to comment.