Beispiel #1
0
class PythonGenerator(Generator):
    '''Python code generator.'''

    @classmethod
    def create_cli(cls):
        return PythonGeneratorCli()

    def __init__(self, out, module_names=None):
        super(PythonGenerator, self).__init__(out)

        self.module_mapper = ModuleMapper(module_names)
        self.filters = _PythonFilters(self.module_mapper)
        self.templates = Templates(__file__, filters=self.filters)

    def generate(self, package):
        self._generate_modules(package.modules)
        self._generate_init_files(package.modules)

    def _generate_modules(self, modules):
        for module in modules:
            code = self._render_module(module)
            filename = self._filename(module)

            self.write_file(filename, code)

    def _generate_init_files(self, modules):
        for module in modules:
            filename = self._init_filename(module)
            filepath = os.path.join(self.out, filename)

            if not os.path.exists(filepath):
                self.write_file(filename, '# encoding: utf-8')

    def _render_module(self, module):
        # Render module definitions.
        definitions = [self._render_definition(d) for d in module.definitions]

        # Render the module.
        return self.templates.render(MODULE_TEMPLATE, imported_modules=module.imported_modules,
                                     definitions=definitions, generated_by=GENERATED_BY)

    def _render_definition(self, def0):
        tname = DEFINITION_TEMPLATES.get(def0.type)
        if not tname:
            raise ValueError('Unsupported definition %r' % def0)

        template = self.templates.get(tname)
        try:
            self.filters.current_module = def0.module
            if def0.is_enum:
                return template.render(enum=def0)
            elif def0.is_message:
                return template.render(message=def0)
            else:
                return template.render(interface=def0)
        finally:
            self.filters.current_module = None

    def _filename(self, module):
        path = self.filters.pymodule(module)
        return path.replace('.', '/') + '.py'

    def _init_filename(self, module):
        filename = self._filename(module)
        path = os.path.dirname(filename)
        return os.path.join(path, '__init__.py')