Esempio n. 1
0
class ObjectiveCGenerator(Generator):
    '''Objective-C code generator.'''

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

    def __init__(self, out, prefixes=None):
        '''Create a new generator.'''
        super(ObjectiveCGenerator, self).__init__(out)

        self.prefix_mapper = PrefixMapper(prefixes)
        self.filters = _ObjectiveCFilters(self.prefix_mapper)
        self.templates = Templates(__file__, filters=self.filters)

    def generate(self, package):
        '''Generate a package source code.'''
        for module in package.modules:
            for definition in module.definitions:
                self._generate_header(definition)
                self._generate_impl(definition)

        self._generate_package(package)

    def _generate_header(self, definition):
        '''Generate a definition header file.'''
        code = self.templates.render(HEADER_TEMPLATE, definition=definition)
        filename = '%s.h' % self.filters.objc_name(definition)
        self.write_file(filename, code)
        return code

    def _generate_impl(self, definition):
        '''Generate a definition implementation file.'''
        code = self.templates.render(IMPL_TEMPLATE, definition=definition)
        filename = '%s.m' % self.filters.objc_name(definition)
        self.write_file(filename, code)
        return code

    def _generate_package(self, package):
        '''Generate a package file which groups all headers.'''
        code = self.templates.render(PACKAGE_TEMPLATE, package=package)

        names = set()
        for module in package.modules:
            for definition in module.definitions:
                names.add(self.filters.objc_name(definition).lower())

        # Generate a unique package file name.
        name = package.name
        while name in names:
            name += '_package'

        # Convert it into a CamelCase string.
        name = name.title().replace('_', '')

        # Write the package header file.
        filename = '%s.h' % name
        self.write_file(filename, code)
        return code
Esempio n. 2
0
class ExampleGenerator(Generator):
    """Example generator template."""

    @classmethod
    def create_cli(cls):
        """Create and return a generator command-line interface."""
        return ExampleGeneratorCli()

    def __init__(self, out, module_names=None, prefixes=None):
        """Create a new generator."""
        super(ExampleGenerator, self).__init__(out)
        self.module_mapper = ModuleMapper(module_names)
        self.prefix_mapper = PrefixMapper(prefixes)

        # Generator filters available in jinja templates.
        self.filters = ExampleFilters(self.module_mapper, self.prefix_mapper)

        # Jinja templates relative to this file.
        self.templates = Templates(__file__, filters=self.filters)

    def generate(self, package):
        """Generate a package source code."""
        for module in package.modules:
            for definition in module.definitions:
                code = self._generate_definition(definition)
                filename = self._definition_filename(definition)
                self.write_file(filename, code)

            code = self.templates.render(MODULE_TEMPLATE, module=module)
            filename = self._module_filename(module)
            self.write_file(filename, code)

    def _generate_definition(self, definition):
        if definition.is_enum:
            return self.templates.render(ENUM_TEMPLATE, enum=definition)

        elif definition.is_message:
            return self.templates.render(MESSAGE_TEMPLATE, message=definition)

        elif definition.is_interface:
            return self.templates.render(INTERFACE_TEMPLATE, interface=definition)

        raise ValueError("Unsupported definition %r" % definition)

    def _definition_filename(self, definition):
        dirname = self._module_directory(definition.module)
        name = self.filters.example_name(definition)
        return "%s/%s.json" % (dirname, name)

    def _module_directory(self, module):
        """Return a module directory name from a module.fullname."""
        name = self.filters.example_module(module)
        return name.replace(".", "/")

    def _module_filename(self, module):
        """Return a module filename."""
        dirname = self._module_directory(module)
        return "%s.json" % dirname
Esempio n. 3
0
class JavaGenerator(Generator):
    '''Java code generator.'''

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

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

        self.module_mapper = ModuleMapper(module_names)
        self.prefix_mapper = PrefixMapper(prefixes)

        self.filters = _JavaFilters(self.module_mapper, self.prefix_mapper)
        self.templates = Templates(__file__, filters=self.filters)

    def generate(self, package):
        for module in package.modules:
            for def0 in module.definitions:
                self._write(def0)

    def _write(self, def0):
        # Render the code.
        code = self._render(def0)

        # Create module directories.
        package_path = self._package_path(def0)
        mkdir_p(package_path)

        # Write a file.
        path = self._file_path(def0)
        with io.open(path, 'wt', encoding=UTF8) as f:
            f.write(code)

        logging.debug('Created %s', path)

    def _render(self, def0):
        if def0.is_enum:
            return self.templates.render(ENUM_TEMPLATE, enum=def0, generated_by=GENERATED_BY)
        elif def0.is_message:
            return self.templates.render(MESSAGE_TEMPLATE, message=def0, generated_by=GENERATED_BY)
        elif def0.is_interface:
            return self.templates.render(INTERFACE_TEMPLATE, interface=def0,
                                         generated_by=GENERATED_BY)
        raise ValueError('Unsupported definition %r' % def0)

    def _package_path(self, def0):
        package = self.filters.jpackage(def0.module)
        dirs = package.split('.')
        return os.path.join(self.out, os.path.join(*dirs))

    def _file_path(self, def0):
        dirname = self._package_path(def0)
        filename = '%s.java' % self.filters.jname(def0)
        return os.path.join(dirname, filename)
Esempio n. 4
0
    def __init__(self, out, prefixes=None):
        '''Create a new generator.'''
        super(ObjectiveCGenerator, self).__init__(out)

        self.prefix_mapper = PrefixMapper(prefixes)
        self.filters = _ObjectiveCFilters(self.prefix_mapper)
        self.templates = Templates(__file__, filters=self.filters)
Esempio n. 5
0
    def __init__(self, out, module_names=None, prefixes=None):
        super(JavaGenerator, self).__init__(out)

        self.module_mapper = ModuleMapper(module_names)
        self.prefix_mapper = PrefixMapper(prefixes)

        self.filters = _JavaFilters(self.module_mapper, self.prefix_mapper)
        self.templates = Templates(__file__, filters=self.filters)
Esempio n. 6
0
    def __init__(self, out, module_names=None, prefixes=None):
        """Create a new generator."""
        super(ExampleGenerator, self).__init__(out)
        self.module_mapper = ModuleMapper(module_names)
        self.prefix_mapper = PrefixMapper(prefixes)

        # Generator filters available in jinja templates.
        self.filters = ExampleFilters(self.module_mapper, self.prefix_mapper)

        # Jinja templates relative to this file.
        self.templates = Templates(__file__, filters=self.filters)
Esempio n. 7
0
 def __init__(self, out, module_names=None, **kwargs):
     super(PythonGenerator, self).__init__(out, module_names=module_names, **kwargs)
     self.filters = _PythonFilters(self.module_mapper)
     self.templates = Templates(__file__, filters=self.filters)
Esempio n. 8
0
class PythonGenerator(Generator):
    '''Python code generator, supports module names, does not support prefixes.'''
    def __init__(self, out, module_names=None, **kwargs):
        super(PythonGenerator, self).__init__(out, module_names=module_names, **kwargs)
        self.filters = _PythonFilters(self.module_mapper)
        self.templates = Templates(__file__, filters=self.filters)

    def generate(self, package):
        # In python __init__.py is required when there are submodules in a module.
        # mycompany                => mycompany/__init__.py
        # mycompany.service        => mycompany/service/__init__.py
        # mycompany.service.client => mycompany/service/client.py

        # Calculate __init__ modules.
        modules = list(package.modules)
        init_names = self._init_modules([module.name for module in modules])

        # Write python modules.
        for module in modules:
            name = module.name
            code = self._render_module(module)

            is_init_module = name in init_names
            init_names.discard(name)

            filename = self._filename(name, is_init_module)
            self._write_file(filename, code)

        # Write non-existent __init__.py files.
        for name in init_names:
            filename = self._filename(name, is_init_module=True)
            if not os.path.exists(filename):
                self._write_file(filename, INIT_FILE_CONTENT)

    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)

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

    def _filename(self, module_name, is_init_module=False):
        path = self.filters.pymodule_name(module_name)
        path = os.path.join(self.out, path.replace('.', '/'))

        if is_init_module:
            return path + '/__init__.py'
        else:
            return path + '.py'

    def _init_modules(self, module_names):
        result = set()

        for name in module_names:
            if '.' not in name:
                continue

            parts = name.split('.')[:-1]
            while parts:
                init_module = '.'.join(parts)
                result.add(init_module)
                parts.pop()

        return result

    def _write_file(self, filename, content):
        dirname = os.path.dirname(filename)
        mkdir_p(dirname)

        with io.open(filename, 'wt', encoding=UTF8) as f:
            f.write(content)

        logging.debug('Created %s', filename)
Esempio n. 9
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')