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')