美文网首页程序员
撸一个简单的Python模板引擎来生成代码

撸一个简单的Python模板引擎来生成代码

作者: 淡定小问题 | 来源:发表于2017-07-26 20:15 被阅读165次

    模板

    利用python的动态性,动态生成脚本代码
    利用python的语法,支持一定的结构:for ,if ;方法调用等

    package  *.*;
    
    import *.ProguardKeep;
    import *.LogType;
    import *.Track;
    
    /**
     * {% for comment in idl.cls_comments: %}
     * {{comment.strip()}}
     * {% end %}
     * schema: {{ idl.file }}
     * Created by AUTO_GEN_CODE on {{ idl.date }}.
     */
    @Track(isRealTime = {{ 'true' if idl.is_real_time else 'false' }}, md_etype = LogType.{{idl.etype.title()}}, md_eid = "{{idl.eid}}", isCarryPathInfo = {{ 'true' if idl.is_with_path else 'false'}})
    public class {{ idl.cls_name }} implements ProguardKeep {
    
        {% for field in idl.fields: %}
        public String {{ field.name }} = ""; // {{ field.comment }}
        {% end %}
    }
    
    

    简单的模板引擎

    import re
    
    TEMPLATE_PATTERN = re.compile("{{(?P<var>.*?)}}|{%(?P<code>.*?)%}")
    
    
    def parse_template(template):
        start = 0
        find_pattern = TEMPLATE_PATTERN.search(template, 0)
    
        while find_pattern:
            segment = template[start: find_pattern.start()]
            var = find_pattern.group('var')
            _code = find_pattern.group('code')
    
            yield segment, var, _code
    
            start = find_pattern.end()
            find_pattern = TEMPLATE_PATTERN.search(template, start)
    
        yield template[start:], None, None
    
    
    class CodeBuilder:
        INDENT = ' ' * 4
    
        def __init__(self):
            self.codes = []
            self.cur_intent = 0
            pass
    
        def __repr__(self):
            return '\n'.join(self.codes)
    
        def add(self, string):
            self.codes.append(self.cur_intent * CodeBuilder.INDENT + string)
            return self
    
        def indent(self):
            self.cur_intent += 1
            return self
    
        def dedent(self):
            self.cur_intent -= 1
            return self
    
    
    def compile_2_code(template):
        builder = CodeBuilder()
    
        builder.add('def gen_code(idl):')
        builder.indent()
    
        builder.add('render_result = []')
        builder.add('__append = render_result.append')
    
        for segment, var, _code in parse_template(template):
    
            builder.add(f"__append('''{segment}''')")
            if var:
                builder.add(f'__append({var.strip()})')
            if _code:
                if _code.strip() == 'end':
                    builder.dedent()
                else:
                    builder.add(f'{_code.strip()}')
                    builder.indent()
    
        builder.add('java_code = "".join(render_result)')
        builder.add('return java_code')
        builder.dedent()
        return repr(builder)
    
    
    if __name__ == '__main__':
        with open('track_code.schema', encoding='utf-8') as f:
            print(compile_2_code(f.read()), file=open('gen_code.py', 'w'))
    
    

    模板引擎生成的代码

    def gen_code(idl):
        render_result = []
        __append = render_result.append
        __append('''package com.meelive.ingkee.mechanism.track.codegen;
    
    import com.meelive.ingkee.base.utils.ProguardKeep;
    import com.meelive.inke.base.track.LogType;
    import com.meelive.inke.base.track.Track;
    
    /**
     * ''')
        for comment in idl.cls_comments:
            __append('''
     * ''')
            __append(comment.strip())
            __append('''
     * ''')
        __append('''
     * schema: ''')
        __append(idl.file)
        __append('''
     * Created by AUTO_GEN_CODE on ''')
        __append(idl.date)
        __append('''.
     */
    @Track(isRealTime = ''')
        __append('true' if idl.is_real_time else 'false')
        __append(''', md_etype = LogType.''')
        __append(idl.etype.title())
        __append(''', md_eid = "''')
        __append(idl.eid)
        __append('''", isCarryPathInfo = ''')
        __append('true' if idl.is_with_path else 'false')
        __append(''')
    public class ''')
        __append(idl.cls_name)
        __append(''' implements ProguardKeep {
    
        ''')
        for field in idl.fields:
            __append('''
        public String ''')
            __append(field.name)
            __append(''' = ""; // ''')
            __append(field.comment)
            __append('''
        ''')
        __append('''
    }
    ''')
        java_code = "".join(render_result)
        return java_code
    
    

    相关文章

      网友评论

        本文标题:撸一个简单的Python模板引擎来生成代码

        本文链接:https://www.haomeiwen.com/subject/nzwokxtx.html