From 217608f1beb6a14d5261894bb2282da715580e23 Mon Sep 17 00:00:00 2001 From: jaska Date: Thu, 28 Feb 2019 18:31:50 +0000 Subject: [PATCH] release 0.4.1 (#241) * Lower dependencies (#232) * :sparkles: port minimum requirement test via pypi-mobans from pyexcel. #187 * :bug: fix travis ci file * :bug: update unit tests * :wheel_chair: lower the dependencies * :lipstick: pump up the version number * Minor code refactoring (#236) * :hammer: code refactoring * :lipstick: reformat code * :books: fix doc build * :bug: fix docs build * Initial prototype for 202 template types (#239) * :hammer: code refactoring * :lipstick: reformat code * :fire: remove MobanEngine's reference to the engine class * :hammer: refactoring the code and un-bury engine instance * :sparkles: initial prototype, not tested. #235 * :books: fix doc build * :bug: fix docs build * :hammer: refactoring. user define template takes precedence * :microscope: test user define engine * :sparkles: associate user defined file extensions with user defined template engine name, i.e. custom_jinja for jinja2, custom_handlebars for handlebars, #235 * :sparkles: take template types from moban file. related to #233 * :hammer: address the feedback * :bug: fix typos and add line feed * :lipstick: beautify the code * :books: provide documentation on template_types under configuration. fix #237 (#240) * :books: update change log.#232, #235 * :lipstick: address review feedback --- .moban.cd/changelog.yml | 7 +++ .moban.cd/moban.yml | 12 ++--- .moban.d/custom_conf.py.jj2 | 3 ++ .moban.d/travis.yml | 12 ++++- .travis.yml | 10 +++- CHANGELOG.rst | 13 +++++ docs/conf.py | 50 ++----------------- .../.moban.cd/data.base.yaml | 2 + .../.moban.yml | 11 ++++ .../README.rst | 35 +++++++++++++ .../a.template.file_type_of_my_choice | 2 + .../data.yml | 2 + .../.moban.cd/data.base.yaml | 2 +- docs/level-4-single-command/data.yml | 2 +- min_requirements.txt | 7 +++ moban/_version.py | 2 +- moban/constants.py | 5 ++ moban/jinja2/engine.py | 15 ++++-- moban/mobanfile/__init__.py | 6 +++ moban/plugins/__init__.py | 4 +- moban/plugins/template.py | 47 +++++++++++------ moban/repo.py | 2 +- mobanfile | 3 +- requirements.txt | 8 +-- setup.py | 11 ++-- .../mobanengine/sample_template_type.yml | 10 ++++ .../test_command_line_options.py | 34 ++++++------- tests/mobanfile/test_mobanfile.py | 2 +- tests/mobanfile/test_templates.py | 5 +- tests/test_docs.py | 7 +++ tests/test_engine.py | 10 ++-- tests/test_jinja2_extensions.py | 4 +- tests/test_template.py | 37 +++++++++++++- 33 files changed, 260 insertions(+), 122 deletions(-) create mode 100644 .moban.d/custom_conf.py.jj2 create mode 100644 docs/level-18-user-defined-template-types/.moban.cd/data.base.yaml create mode 100644 docs/level-18-user-defined-template-types/.moban.yml create mode 100644 docs/level-18-user-defined-template-types/README.rst create mode 100644 docs/level-18-user-defined-template-types/a.template.file_type_of_my_choice create mode 100644 docs/level-18-user-defined-template-types/data.yml create mode 100644 min_requirements.txt create mode 100644 tests/fixtures/mobanengine/sample_template_type.yml diff --git a/.moban.cd/changelog.yml b/.moban.cd/changelog.yml index 12c99229..d958dc28 100644 --- a/.moban.cd/changelog.yml +++ b/.moban.cd/changelog.yml @@ -1,6 +1,13 @@ name: moban organisation: moremoban releases: +- changes: + - action: Added + details: + - "`#235`: user defined template types so that custom file extensions, template configurations can be controlled by moban user" + - "`#232`: the package dependencies have been fine tuning to lower versions, most of them are dated back to 2017." + date: unreleased + version: 0.4.1 - changes: - action: Added details: diff --git a/.moban.cd/moban.yml b/.moban.cd/moban.yml index 2585b9f1..2e058014 100644 --- a/.moban.cd/moban.yml +++ b/.moban.cd/moban.yml @@ -4,8 +4,8 @@ organisation: moremoban author: C. W. contact: wangc_2011@hotmail.com license: MIT -version: 0.4.0 -current_version: 0.4.0 +version: 0.4.1 +current_version: 0.4.1 release: 0.4.0 branch: master master: index @@ -21,9 +21,9 @@ dependencies: - ruamel.yaml>=0.15.5 - jinja2>=2.7.1 - lml>=0.0.9 - - appdirs==1.4.3 - - crayons - - GitPython==2.1.11 - - giturlparse + - appdirs>=1.2.0 + - crayons>= 0.1.0 + - GitPython>=2.0.0 + - giturlparse>=0.9.1 description: Yet another jinja2 cli command for static text generation scm_host: github.com diff --git a/.moban.d/custom_conf.py.jj2 b/.moban.d/custom_conf.py.jj2 new file mode 100644 index 00000000..1edecbb7 --- /dev/null +++ b/.moban.d/custom_conf.py.jj2 @@ -0,0 +1,3 @@ +{% include "conf.py.jj2" %} + +master_doc = "index" diff --git a/.moban.d/travis.yml b/.moban.d/travis.yml index 3408a1ba..741fd994 100644 --- a/.moban.d/travis.yml +++ b/.moban.d/travis.yml @@ -1,9 +1,17 @@ {% extends 'travis.yml.jj2' %} +{%block extra_matrix %} +matrix: + include: + - python: 2.7 + env: MINREQ=1 +{%endblock%} + {%block custom_python_versions%} python: - - pypy-5.3.1 - - 3.7-dev + - &pypy2 pypy2.7-6.0 + - 3.8-dev + - 3.7 - 3.6 - 3.5 - 2.7 diff --git a/.travis.yml b/.travis.yml index 16330f5a..3fa8fc09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,19 @@ sudo: false +dist: xenial language: python notifications: email: false python: - - pypy-5.3.1 - - 3.7-dev + - &pypy2 pypy2.7-6.0 + - 3.8-dev + - 3.7 - 3.6 - 3.5 - 2.7 +matrix: + include: + - python: 2.7 + env: MINREQ=1 before_install: - if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then pip install flake8==2.6.2; fi - if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e711278a..158e43bf 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,19 @@ Change log ================================================================================ +0.4.1 - unreleased +-------------------------------------------------------------------------------- + +Added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `#235 `_: user defined + template types so that custom file extensions, template configurations can be + controlled by moban user +#. `#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 -------------------------------------------------------------------------------- diff --git a/docs/conf.py b/docs/conf.py index ce8629fe..3e4e6c8c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,13 +24,11 @@ project = 'moban' copyright = '2017-2019 Onni Software Ltd. and its contributors' author = 'Onni Software Ltd.' - # The short X.Y version -version = '0.4.0' +version = '0.4.1' # The full version, including alpha/beta/rc tags release = '0.4.0' - # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -41,15 +39,6 @@ # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # @@ -70,51 +59,16 @@ # html_theme = 'alabaster' -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} - - -# -- Options for Epub output ------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = project - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -# -# epub_identifier = '' - -# A unique identification for the text. -# -# epub_uid = '' - -# A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] - # -- Extension configuration ------------------------------------------------- # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None} - # TODO: html_theme not configurable upstream html_theme = 'default' @@ -128,3 +82,5 @@ ] intersphinx_mapping.update({ }) + +master_doc = "index" diff --git a/docs/level-18-user-defined-template-types/.moban.cd/data.base.yaml b/docs/level-18-user-defined-template-types/.moban.cd/data.base.yaml new file mode 100644 index 00000000..3a35fadb --- /dev/null +++ b/docs/level-18-user-defined-template-types/.moban.cd/data.base.yaml @@ -0,0 +1,2 @@ +nihao: shijie +hello: shijie diff --git a/docs/level-18-user-defined-template-types/.moban.yml b/docs/level-18-user-defined-template-types/.moban.yml new file mode 100644 index 00000000..5a7870a2 --- /dev/null +++ b/docs/level-18-user-defined-template-types/.moban.yml @@ -0,0 +1,11 @@ +configuration: + template_types: + my_own_type: + base_type: jinja2 + file_extensions: + - file_type_of_my_choice + options: + extensions: + - jinja2_time.TimeExtension +targets: + - a.output: a.template.file_type_of_my_choice diff --git a/docs/level-18-user-defined-template-types/README.rst b/docs/level-18-user-defined-template-types/README.rst new file mode 100644 index 00000000..49abd720 --- /dev/null +++ b/docs/level-18-user-defined-template-types/README.rst @@ -0,0 +1,35 @@ +Level 18: User defined template types +================================================================================ + +Since moban version 4.1, custom template types can be defined to deviate from +default configurations of the template engines. In addition, the configuration +possibilities are: + +#. associate your own file extensions +#. choose your own template engine extensions +#. + + +Evaluation +-------------------------------------------------------------------------------- + +Please go to `docs/level-4-single-command` directory. + + +Here is the `.moban.yml`, which inserts `template_types` on top of the moban +file found in level 4:: + + configuration: + template_types: + my_own_type: + base_type: jinja2 + file_extensions: + - file_type_of_my_choice + options: + extensions: + - jinja2_time.TimeExtension + targets: + - a.output: a.template.file_type_of_my_choice + + +where `template_types` is a dictionary of different custom types diff --git a/docs/level-18-user-defined-template-types/a.template.file_type_of_my_choice b/docs/level-18-user-defined-template-types/a.template.file_type_of_my_choice new file mode 100644 index 00000000..b6f2647e --- /dev/null +++ b/docs/level-18-user-defined-template-types/a.template.file_type_of_my_choice @@ -0,0 +1,2 @@ +{% now 'utc' %} + diff --git a/docs/level-18-user-defined-template-types/data.yml b/docs/level-18-user-defined-template-types/data.yml new file mode 100644 index 00000000..168bfb12 --- /dev/null +++ b/docs/level-18-user-defined-template-types/data.yml @@ -0,0 +1,2 @@ +overrides: data.base.yaml +hello: world diff --git a/docs/level-4-single-command/.moban.cd/data.base.yaml b/docs/level-4-single-command/.moban.cd/data.base.yaml index 2c16d47a..3a35fadb 100644 --- a/docs/level-4-single-command/.moban.cd/data.base.yaml +++ b/docs/level-4-single-command/.moban.cd/data.base.yaml @@ -1,2 +1,2 @@ nihao: shijie -hello: shijie \ No newline at end of file +hello: shijie diff --git a/docs/level-4-single-command/data.yml b/docs/level-4-single-command/data.yml index 7813e820..168bfb12 100644 --- a/docs/level-4-single-command/data.yml +++ b/docs/level-4-single-command/data.yml @@ -1,2 +1,2 @@ overrides: data.base.yaml -hello: world \ No newline at end of file +hello: world diff --git a/min_requirements.txt b/min_requirements.txt new file mode 100644 index 00000000..3f7c2ca6 --- /dev/null +++ b/min_requirements.txt @@ -0,0 +1,7 @@ +ruamel.yaml==0.15.5 +jinja2==2.7.1 +lml==0.0.9 +appdirs==1.2.0 +crayons== 0.1.0 +GitPython==2.0.0 +giturlparse==0.9.1 diff --git a/moban/_version.py b/moban/_version.py index 44e5b7dc..29b35a50 100644 --- a/moban/_version.py +++ b/moban/_version.py @@ -1,2 +1,2 @@ -__version__ = "0.4.0" +__version__ = "0.4.1" __author__ = "C. W." diff --git a/moban/constants.py b/moban/constants.py index f113c83a..920c5e54 100644 --- a/moban/constants.py +++ b/moban/constants.py @@ -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" @@ -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" diff --git a/moban/jinja2/engine.py b/moban/jinja2/engine.py index e51af380..0d525f0d 100644 --- a/moban/jinja2/engine.py +++ b/moban/jinja2/engine.py @@ -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 @@ -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 diff --git a/moban/mobanfile/__init__.py b/moban/mobanfile/__init__.py index dcab849c..455b30f2 100644 --- a/moban/mobanfile/__init__.py +++ b/moban/mobanfile/__init__.py @@ -62,6 +62,12 @@ def handle_moban_file_v1(moban_file_configurations, command_line_options): if extensions: plugins.ENGINES.register_extensions(extensions) + template_types = merged_options.get( + constants.LABEL_TEMPLATE_TYPES + ) + if template_types: + plugins.ENGINES.register_options(template_types) + if targets: if target: targets = target diff --git a/moban/plugins/__init__.py b/moban/plugins/__init__.py index 0fcc020c..9458e5ed 100644 --- a/moban/plugins/__init__.py +++ b/moban/plugins/__init__.py @@ -1,5 +1,5 @@ from lml.loader import scan_plugins_regex -from moban.plugins.template import TemplateFactory +from moban.plugins.template import MobanFactory from moban import constants @@ -11,7 +11,7 @@ ] -ENGINES = TemplateFactory() +ENGINES = MobanFactory() def make_sure_all_pkg_are_loaded(): diff --git a/moban/plugins/template.py b/moban/plugins/template.py index 9595ea1d..0a9f08e1 100644 --- a/moban/plugins/template.py +++ b/moban/plugins/template.py @@ -12,41 +12,56 @@ log = logging.getLogger(__name__) -class TemplateFactory(PluginManager): +class MobanFactory(PluginManager): def __init__(self): - super(TemplateFactory, self).__init__( - constants.TEMPLATE_ENGINE_EXTENSION - ) + 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 TemplateEngine( - 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 TemplateEngine(object): - def __init__( - self, template_dirs, context_dirs, engine_cls, engine_extensions=None - ): +class MobanEngine(object): + 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 diff --git a/moban/repo.py b/moban/repo.py index 8e04ce5e..36da0582 100644 --- a/moban/repo.py +++ b/moban/repo.py @@ -36,7 +36,7 @@ def get_repo_name(repo_url): try: repo = giturlparse.parse(repo_url) name = repo.repo - if name.endswith('/'): + if name.endswith("/"): name = name[:-1] return name except AttributeError: diff --git a/mobanfile b/mobanfile index 36728477..2360459b 100644 --- a/mobanfile +++ b/mobanfile @@ -9,10 +9,11 @@ targets: - setup.py: setup.py - moban/__init__.py: __init__.py.jj2 - moban/_version.py: _version.py.jj2 - - docs/conf.py: conf.py.jj2 + - docs/conf.py: custom_conf.py.jj2 - .travis.yml: travis.yml - requirements.txt: requirements.txt.jj2 - .gitignore: moban_gitignore.jj2 - output: CHANGELOG.rst configuration: changelog.yml template: CHANGELOG.rst.jj2 + - min_requirements.txt: min_requirements.txt.jj2 diff --git a/requirements.txt b/requirements.txt index d3fe44bb..7dd42624 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ ruamel.yaml>=0.15.5 jinja2>=2.7.1 lml>=0.0.9 -appdirs==1.4.3 -crayons -GitPython==2.1.11 -giturlparse +appdirs>=1.2.0 +crayons>= 0.1.0 +GitPython>=2.0.0 +giturlparse>=0.9.1 diff --git a/setup.py b/setup.py index bc9f24a6..bd4b43c2 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ NAME = 'moban' AUTHOR = 'C. W.' -VERSION = '0.4.0' +VERSION = '0.4.1' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'MIT' ENTRY_POINTS = { @@ -65,10 +65,10 @@ 'ruamel.yaml>=0.15.5', 'jinja2>=2.7.1', 'lml>=0.0.9', - 'appdirs==1.4.3', - 'crayons', - 'GitPython==2.1.11', - 'giturlparse', + 'appdirs>=1.2.0', + 'crayons>= 0.1.0', + 'GitPython>=2.0.0', + 'giturlparse>=0.9.1', ] SETUP_COMMANDS = {} @@ -189,6 +189,7 @@ def filter_out_test_code(file_handle): if __name__ == '__main__': setup( + test_suite="tests", name=NAME, author=AUTHOR, version=VERSION, diff --git a/tests/fixtures/mobanengine/sample_template_type.yml b/tests/fixtures/mobanengine/sample_template_type.yml new file mode 100644 index 00000000..60eeb617 --- /dev/null +++ b/tests/fixtures/mobanengine/sample_template_type.yml @@ -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 diff --git a/tests/integration_tests/test_command_line_options.py b/tests/integration_tests/test_command_line_options.py index aea42b2e..6cbe3fe6 100644 --- a/tests/integration_tests/test_command_line_options.py +++ b/tests/integration_tests/test_command_line_options.py @@ -18,7 +18,7 @@ def setUp(self): ) self.patcher1.start() - @patch("moban.plugins.template.TemplateEngine.render_to_file") + @patch("moban.plugins.template.MobanEngine.render_to_file") def test_custom_options(self, fake_template_doer): test_args = [ "moban", @@ -39,7 +39,7 @@ def test_custom_options(self, fake_template_doer): "a.jj2", "config.yaml", "moban.output" ) - @patch("moban.plugins.template.TemplateEngine.render_to_file") + @patch("moban.plugins.template.MobanEngine.render_to_file") def test_minimal_options(self, fake_template_doer): test_args = ["moban", "-c", self.config_file, "-t", "a.jj2"] with patch.object(sys, "argv", test_args): @@ -73,7 +73,7 @@ def setUp(self): ) self.patcher1.start() - @patch("moban.plugins.template.TemplateEngine.render_to_file") + @patch("moban.plugins.template.MobanEngine.render_to_file") def test_default_options(self, fake_template_doer): test_args = ["moban", "-t", "a.jj2"] with patch.object(sys, "argv", test_args): @@ -84,7 +84,7 @@ def test_default_options(self, fake_template_doer): "a.jj2", "data.yml", "moban.output" ) - @patch("moban.plugins.template.TemplateEngine.render_string_to_file") + @patch("moban.plugins.template.MobanEngine.render_string_to_file") def test_string_template(self, fake_template_doer): string_template = "{{HELLO}}" test_args = ["moban", string_template] @@ -133,7 +133,7 @@ def setUp(self): ) self.patcher1.start() - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_single_command(self, fake_template_doer): test_args = ["moban"] with patch.object(sys, "argv", test_args): @@ -152,7 +152,7 @@ def test_single_command(self, fake_template_doer): ) @raises(Exception) - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_single_command_with_missing_output(self, fake_template_doer): test_args = ["moban", "-t", "README.rst.jj2"] with patch.object(sys, "argv", test_args): @@ -160,7 +160,7 @@ def test_single_command_with_missing_output(self, fake_template_doer): main() - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_single_command_with_a_few_options(self, fake_template_doer): test_args = ["moban", "-t", "README.rst.jj2", "-o", "xyz.output"] with patch.object(sys, "argv", test_args): @@ -173,7 +173,7 @@ def test_single_command_with_a_few_options(self, fake_template_doer): [TemplateTarget("README.rst.jj2", "data.yaml", "xyz.output")], ) - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_single_command_with_options(self, fake_template_doer): test_args = [ "moban", @@ -223,7 +223,7 @@ def setUp(self): ) self.patcher1.start() - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_single_command(self, fake_template_doer): test_args = ["moban"] with patch.object(sys, "argv", test_args): @@ -261,7 +261,7 @@ def setUp(self): ) self.patcher1.start() - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_single_command(self, fake_template_doer): test_args = ["moban", "-m", self.config_file] with patch.object(sys, "argv", test_args): @@ -296,7 +296,7 @@ def setUp(self): ) self.patcher1.start() - @patch("moban.plugins.template.TemplateEngine.render_to_file") + @patch("moban.plugins.template.MobanEngine.render_to_file") def test_template_option_override_moban_file(self, fake_template_doer): test_args = ["moban", "-t", "setup.py.jj2"] with patch.object(sys, "argv", test_args): @@ -307,7 +307,7 @@ def test_template_option_override_moban_file(self, fake_template_doer): "setup.py.jj2", "data.yml", "moban.output" ) - @patch("moban.plugins.template.TemplateEngine.render_to_file") + @patch("moban.plugins.template.MobanEngine.render_to_file") def test_template_option_not_in_moban_file(self, fake_template_doer): test_args = ["moban", "-t", "foo.jj2"] with patch.object(sys, "argv", test_args): @@ -340,7 +340,7 @@ def setUp(self): self.config_file = ".moban.yml" @raises(SystemExit) - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_no_configuration(self, fake_template_doer): with open(self.config_file, "w") as f: f.write("") @@ -351,7 +351,7 @@ def test_no_configuration(self, fake_template_doer): main() @raises(SystemExit) - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_no_configuration_2(self, fake_template_doer): with open(self.config_file, "w") as f: f.write("not: related") @@ -362,7 +362,7 @@ def test_no_configuration_2(self, fake_template_doer): main() @raises(SystemExit) - @patch("moban.plugins.template.TemplateEngine.render_to_files") + @patch("moban.plugins.template.MobanEngine.render_to_files") def test_no_targets(self, fake_template_doer): with open(self.config_file, "w") as f: f.write("configuration: test") @@ -395,7 +395,7 @@ def test_single_command(self, _): from moban.main import main with patch( - "moban.plugins.template.TemplateEngine.render_to_files" + "moban.plugins.template.MobanEngine.render_to_files" ) as fake: main() call_args = list(fake.call_args[0][0]) @@ -420,7 +420,7 @@ def setUp(self): with open(self.config_file, "w") as f: f.write("hello: world") - @patch("moban.plugins.template.TemplateEngine.render_to_file") + @patch("moban.plugins.template.MobanEngine.render_to_file") def test_mako_option(self, fake_template_doer): test_args = ["moban", "-t", "a.mako"] with patch.object(sys, "argv", test_args): diff --git a/tests/mobanfile/test_mobanfile.py b/tests/mobanfile/test_mobanfile.py index 2cffe17c..0786108d 100644 --- a/tests/mobanfile/test_mobanfile.py +++ b/tests/mobanfile/test_mobanfile.py @@ -112,7 +112,7 @@ def test_is_repo(): eq_(expected, actual) -@patch("moban.plugins.template.TemplateEngine.render_to_files") +@patch("moban.plugins.template.MobanEngine.render_to_files") def test_handle_targets(fake_renderer): from moban.mobanfile import handle_targets diff --git a/tests/mobanfile/test_templates.py b/tests/mobanfile/test_templates.py index 620e4e12..02479212 100644 --- a/tests/mobanfile/test_templates.py +++ b/tests/mobanfile/test_templates.py @@ -59,7 +59,10 @@ def test_listing_dir_recusively(self): None, ), ] - eq_(expected, results) + eq_( + sorted(expected, key=lambda x: x[0]), + sorted(results, key=lambda x: x[0]), + ) @patch("moban.reporter.report_error_message") def test_listing_dir_recusively_with_error(self, reporter): diff --git a/tests/test_docs.py b/tests/test_docs.py index 1d6db334..3baa045a 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -235,6 +235,13 @@ def test_level_17_force_template_type_from_moban_file(self): folder = "level-17-force-template-type-from-moban-file" self._raw_moban(["moban"], folder, expected, "simple.file") + def test_level_18_user_defined_template_types(self): + from datetime import datetime + expected = "{date}\n".format(date=datetime.now().strftime("%Y-%m-%d")) + + folder = "level-18-user-defined-template-types" + self._raw_moban(["moban"], folder, expected, "a.output") + def test_misc_1(self): expected = "test file\n" diff --git a/tests/test_engine.py b/tests/test_engine.py index 5b45e6a3..62ed8bb2 100644 --- a/tests/test_engine.py +++ b/tests/test_engine.py @@ -13,7 +13,7 @@ import_module_of_extension, ) from moban.plugins.context import Context -from moban.plugins.template import TemplateEngine, expand_template_directories +from moban.plugins.template import MobanEngine, expand_template_directories USER_HOME = os.path.join("user", "home", ".moban", "repos") @@ -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: @@ -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) @@ -63,12 +63,12 @@ def test_unknown_template_type(): @raises(exceptions.DirectoryNotFound) def test_non_existent_tmpl_directries(): - TemplateEngine("abc", "tests", Engine) + MobanEngine("abc", "tests", Engine) @raises(exceptions.DirectoryNotFound) def test_non_existent_config_directries(): - TemplateEngine("tests", "abc", Engine) + MobanEngine("tests", "abc", Engine) @raises(exceptions.DirectoryNotFound) diff --git a/tests/test_jinja2_extensions.py b/tests/test_jinja2_extensions.py index e2eba845..f9009fcb 100644 --- a/tests/test_jinja2_extensions.py +++ b/tests/test_jinja2_extensions.py @@ -3,7 +3,7 @@ from nose.tools import eq_ from moban.jinja2.engine import Engine -from moban.plugins.template import TemplateEngine +from moban.plugins.template import MobanEngine from moban.jinja2.extensions import jinja_global @@ -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 = TemplateEngine([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() diff --git a/tests/test_template.py b/tests/test_template.py index f00940f9..d9b9d2b3 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -1,14 +1,17 @@ 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" -@patch(MODULE + ".TemplateEngine._render_with_finding_data_first") +@patch(MODULE + ".MobanEngine._render_with_finding_data_first") def test_do_templates_1(_do_templates_with_more_shared_data): jobs = [ TemplateTarget("1.template", "data.yml", "1.output"), @@ -31,7 +34,7 @@ def test_do_templates_1(_do_templates_with_more_shared_data): _do_templates_with_more_shared_data.assert_called_with(expected) -@patch(MODULE + ".TemplateEngine._render_with_finding_template_first") +@patch(MODULE + ".MobanEngine._render_with_finding_template_first") def test_do_templates_2(_do_templates_with_more_shared_templates): jobs = [ TemplateTarget("1.template", "data1.yml", "1.output"), @@ -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)