From 5299c033e58eb5a7d56869b00ebfb3c49b027aee Mon Sep 17 00:00:00 2001 From: wjmcat <1435130236@qq.com> Date: Fri, 26 Jun 2020 21:51:26 +0800 Subject: [PATCH] complete simple version of code-generator --- examples/config/base_model.json | 10 ++++++ examples/plugins/base.plugin.jinja2 | 10 ++++++ examples/templates/index.html.jinja2 | 15 ++++++++ plugins/base.plugin.jinja2 | 0 setup.py | 53 ++++++++++++++++++++++++++++ src/code_generator/config.py | 4 ++- src/code_generator/loader.py | 32 +++++++++++------ src/code_generator/main.py | 43 +++++++++++++++++----- 8 files changed, 148 insertions(+), 19 deletions(-) create mode 100644 examples/config/base_model.json create mode 100644 examples/plugins/base.plugin.jinja2 create mode 100644 examples/templates/index.html.jinja2 delete mode 100644 plugins/base.plugin.jinja2 create mode 100644 setup.py diff --git a/examples/config/base_model.json b/examples/config/base_model.json new file mode 100644 index 0000000..b567319 --- /dev/null +++ b/examples/config/base_model.json @@ -0,0 +1,10 @@ +{ + "model": "基础模型", + "columns": [{ + "name": "1" + },{ + "name": "22" + },{ + "name": "33" + }] +} \ No newline at end of file diff --git a/examples/plugins/base.plugin.jinja2 b/examples/plugins/base.plugin.jinja2 new file mode 100644 index 0000000..075e8ac --- /dev/null +++ b/examples/plugins/base.plugin.jinja2 @@ -0,0 +1,10 @@ +{%- macro number_input(column) -%} +

number_input

+

{{ column.name }}

+{% endmacro -%} + + +{%- macro date_input(column) -%} +

date_input

+

{{ column.name }}

+{% endmacro -%} diff --git a/examples/templates/index.html.jinja2 b/examples/templates/index.html.jinja2 new file mode 100644 index 0000000..346be00 --- /dev/null +++ b/examples/templates/index.html.jinja2 @@ -0,0 +1,15 @@ +

{{ model }}

+ + \ No newline at end of file diff --git a/plugins/base.plugin.jinja2 b/plugins/base.plugin.jinja2 deleted file mode 100644 index e69de29..0000000 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..28b5f5a --- /dev/null +++ b/setup.py @@ -0,0 +1,53 @@ +""" +Code Generator - https://github.com/wj-Mcat/code-generator + +Authors: Jingjing WU (吴京京) + +2020-now @ Copyright wj-Mcat + +Licensed under the Apache License, Version 2.0 (the 'License'); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an 'AS IS' BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +from setuptools import setup, find_packages + +with open("./VERSION", 'r+') as f: + VERSION = f.read() + +with open('./requirements.txt', 'r+') as f: + requirements = f.readlines() + +setup( + name='code-generator', + version=VERSION, + description="a simple code generator for ", + long_description='a templated code generator for all language, especially ' + 'for boring code', + keywords='code-gen,code-generator,python,code-snippet', + author='wj-Mcat', + author_email='1435130236@qq.com', + license='Apache 2', + packages=find_packages('src'), + package_dir = { + "": "src" + }, + include_package_data=True, + package_data = { + 'code_generator': ['vue/*', 'flask/*', 'element.css', 'index.js', 'jquery.min.js', 'template.html', 'vue.js'] + }, + install_requires=requirements, + entry_points={ + 'console_scripts': [ + 'code-gen = code_generator.main:main' + ] + } +) \ No newline at end of file diff --git a/src/code_generator/config.py b/src/code_generator/config.py index 4112cc2..edabc7e 100644 --- a/src/code_generator/config.py +++ b/src/code_generator/config.py @@ -21,11 +21,13 @@ from __future__ import annotations import logging +from jinja2 import Template + def get_logger(): """get the logger""" log_formatter = logging.Formatter( - fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s') + fmt='%(asctime)s - %(name)s - %(levelname)s - %(filename)s - %(funcName)s - %(message)s') logger = logging.getLogger("CodeGenerator") logger.handlers = [] diff --git a/src/code_generator/loader.py b/src/code_generator/loader.py index 0a5300f..cbef607 100644 --- a/src/code_generator/loader.py +++ b/src/code_generator/loader.py @@ -19,7 +19,7 @@ limitations under the License. """ from __future__ import annotations import os -from typing import Dict +from typing import Dict, Optional from abc import ABCMeta from jinja2 import Template @@ -39,7 +39,7 @@ class Loader(metaclass=ABCMeta): lazy load plugins """ self.files: Dict[str, str] = {} - log.info('load the plugins from : %s', file_or_dir) + log.info('load the files from : %s', file_or_dir) if not os.path.exists(file_or_dir): log.warning('plugin file/dir doesn"t exist, there are ' 'no plugins to load') @@ -82,11 +82,17 @@ class TemplateLoader(Loader): def __init__(self, file_or_dir: str = 'templates'): super(TemplateLoader, self).__init__(file_or_dir) - def load_templates(self) -> Dict[str, Template]: + def load_templates(self, plugins: Optional[str] = None + ) -> Dict[str, Template]: """load template""" self._load_files() templates: Dict[str, Template] = {} for key, template in self.files.items(): + if plugins is not None: + template = "{plugin}\n{template}".format( + plugin=plugins, template=template + ) + log.info(template) templates[key] = Template(template) return templates @@ -102,7 +108,7 @@ class PluginLoader(Loader): def load_to_file(self) -> str: files = self._load_plugins() - return '\n'.join(files) + return '\n'.join(files.values()) def load_plugin_descriptions(self) -> Dict[str, str]: descriptions: Dict[str, str] = {} @@ -113,12 +119,18 @@ class PluginLoader(Loader): attrs = dir(module) macros = [(attr, getattr(module, attr)) for attr in attrs if isinstance(getattr(module, attr), Macro)] - - # find macros description from html node description using bs4 - - + # first we only load the name of plugin + for macro_name, macro in macros: + if macro_name not in descriptions: + descriptions[macro_name] = macro_name return descriptions - - + def load_to_module(self): + """ + load plugins to the instance of module type + :return: + """ + plugin_content = self.load_to_file() + module = Template(plugin_content).module + return module diff --git a/src/code_generator/main.py b/src/code_generator/main.py index 495ec3f..8113d73 100644 --- a/src/code_generator/main.py +++ b/src/code_generator/main.py @@ -18,7 +18,12 @@ See the License for the specific language governing permissions and limitations under the License. """ from __future__ import annotations + +import json from argparse import ArgumentParser +import os + +from jinja2 import Template from .config import get_logger from .loader import TemplateLoader, PluginLoader @@ -32,12 +37,33 @@ def run_server(): pass -def render_by_config(): - file = args['file'] - templates = TemplateLoader(file).load_templates() - plugin_file = PluginLoader(file).load_to_file() +def _save_to_file(template_dir: str, file_name: str, content: str): + if not os.path.exists(template_dir): + os.mkdir(template_dir) + path = os.path.join(template_dir, file_name) + with open(path, 'w', encoding='utf-8') as f: + f.write(content) +def _read_to_json(file: str) -> dict: + """read json file to json data""" + file_path = os.path.join(os.getcwd(), file) + print(file_path) + if not os.path.exists(file_path): + raise FileNotFoundError(f'file <{file}> not found') + with open(file_path, 'r+', encoding='utf-8') as f: + return json.load(f) + + +def render_by_config(): + config = _read_to_json(args['config']) + plugins = PluginLoader(args['plugins']).load_to_file() + log.info(plugins) + templates = TemplateLoader(args['templates']).load_templates(plugins) + for name, template in templates.items(): + result = template.render(config) + base_name = os.path.basename(args['templates']) + '_result' + _save_to_file(base_name, name, result) def main(): @@ -49,15 +75,16 @@ def main(): serve_parser.add_argument('--file', default='config.json', type=str) serve_parser.set_defaults(func=run_server) - config_parser = subparsers.add_parser(name='config') - config_parser.add_argument('--file', default='config.json', type=str) - config_parser.add_argument('--template', default='flask,vue', type=str) + config_parser = subparsers.add_parser(name='render') + config_parser.add_argument('--config', type=str, default='./config.json') + config_parser.add_argument('--templates', type=str, default='./templates') + config_parser.add_argument('--plugins', type=str, default='./plugins') config_parser.set_defaults(func=render_by_config) local_args = parser.parse_args() log.info(args) args.update(local_args.__dict__) - local_args.func(args) + local_args.func() if __name__ == '__main__': -- GitLab