Ejemplo n.º 1
0
def generate(generator_arguments_file: str) -> List[str]:
    mapping = {
        "_idl.pyi.em": "_%s.pyi",
    }
    generated_files: List[str] = generate_files(generator_arguments_file,
                                                mapping)

    args = read_generator_arguments(generator_arguments_file)
    package_name = args["package_name"]

    # For __init__.pyi, it is required to output the exact same contents as
    # rosidl_python does.
    modules: Dict[str, Set[str]] = {}
    idl_content = IdlContent()
    for idl_tuple in args.get("idl_tuples", []):
        idl_parts = idl_tuple.rsplit(":", 1)
        assert len(idl_parts) == 2

        idl_rel_path = pathlib.Path(idl_parts[1])
        idl_stems = modules.setdefault(str(idl_rel_path.parent), set())
        idl_stems.add(idl_rel_path.stem)

        locator = IdlLocator(*idl_parts)
        idl_file = parse_idl_file(locator)
        idl_content.elements += idl_file.content.elements

    for subfolder in modules.keys():
        with open(os.path.join(args["output_dir"], subfolder, "__init__.pyi"),
                  "w") as f:
            for idl_stem in sorted(modules[subfolder]):
                module_name = "_{}".format(
                    convert_camel_case_to_lower_case_underscore(idl_stem))
                f.write(
                    f"from {package_name}.{subfolder}.{module_name} import "
                    f"{idl_stem} as {idl_stem}  # noqa: F401\n")

    return generated_files
Ejemplo n.º 2
0
def generate_rs(generator_arguments_file, typesupport_impls):
    args = read_generator_arguments(generator_arguments_file)
    package_name = args['package_name']

    # expand init modules for each directory
    modules = {}
    idl_content = IdlContent()
    for idl_tuple in args.get('idl_tuples', []):
        idl_parts = idl_tuple.rsplit(':', 1)
        assert len(idl_parts) == 2

        idl_rel_path = pathlib.Path(idl_parts[1])
        idl_stems = modules.setdefault(str(idl_rel_path.parent), set())
        idl_stems.add(idl_rel_path.stem)

        locator = IdlLocator(*idl_parts)
        idl_file = parse_idl_file(locator)
        idl_content.elements += idl_file.content.elements

    typesupport_impls = typesupport_impls.split(';')

    template_dir = args['template_dir']
    type_support_impl_by_filename = {
        '%s_rs.ep.{0}.c'.format(impl): impl
        for impl in typesupport_impls
    }

    mapping_msgs = {
        os.path.join(template_dir, 'msg.rs.em'): ['rust/src/%s.rs'],
        os.path.join(template_dir, 'msg.c.em'): type_support_impl_by_filename.keys(),
    }

    mapping_srvs = {
        os.path.join(template_dir, 'srv.rs.em'): ['rust/src/%s.rs'],
        os.path.join(template_dir, 'srv.c.em'): type_support_impl_by_filename.keys(),
    }

    # Ensure the required templates exist
    for template_file in mapping_msgs.keys():
        assert os.path.exists(template_file), \
            'Messages template file %s not found' % template_file
    for template_file in mapping_srvs.keys():
        assert os.path.exists(template_file), \
            'Services template file %s not found' % template_file

    data = {
        'get_c_type': get_c_type,
        'get_rs_type': get_rs_type,
        'constant_value_to_rs': constant_value_to_rs,
        'value_to_rs': value_to_rs,
        'convert_camel_case_to_lower_case_underscore':
        convert_camel_case_to_lower_case_underscore,
        'convert_lower_case_underscore_to_camel_case':
        convert_lower_case_underscore_to_camel_case,
        'get_builtin_rs_type': get_builtin_rs_type,
        'msg_specs': [],
        'srv_specs': [],
        'package_name': args['package_name'],
        'typesupport_impls': typesupport_impls,
    }
    latest_target_timestamp = get_newest_modification_time(
        args['target_dependencies'])

    for message in idl_content.get_elements_of_type(Message):
        data['msg_specs'].append(('msg', message))

    for service in idl_content.get_elements_of_type(Service):
        data['srv_specs'].append(('srv', service))

    if data['msg_specs']:
        for template_file, generated_filenames in mapping_msgs.items():
            for generated_filename in generated_filenames:
                generated_file = os.path.join(args['output_dir'],
                                              generated_filename % 'msg')
                expand_template(
                    os.path.join(template_dir, template_file),
                    data.copy(),
                    generated_file,
                    minimum_timestamp=latest_target_timestamp)

    if data['srv_specs']:
        for template_file, generated_filenames in mapping_srvs.items():
            for generated_filename in generated_filenames:
                generated_file = os.path.join(args['output_dir'],
                                              generated_filename % 'srv')
                expand_template(
                    os.path.join(template_dir, template_file),
                    data.copy(),
                    generated_file,
                    minimum_timestamp=latest_target_timestamp)

    expand_template(
        os.path.join(template_dir, 'lib.rs.em'),
        data.copy(),
        os.path.join(args['output_dir'], 'rust/src/lib.rs'),
        minimum_timestamp=latest_target_timestamp)

    return 0
Ejemplo n.º 3
0
def extract_content_from_ast(tree):
    content = IdlContent()

    include_directives = tree.find_data('include_directive')
    for include_directive in include_directives:
        assert len(include_directive.children) == 1
        child = include_directive.children[0]
        assert child.data in ('h_char_sequence', 'q_char_sequence')
        include_token = next(child.scan_values(_find_tokens(None)))
        content.elements.append(Include(include_token.value))

    constants = {}
    const_dcls = tree.find_data('const_dcl')
    for const_dcl in const_dcls:
        const_type = next(const_dcl.find_data('const_type'))
        const_expr = next(const_dcl.find_data('const_expr'))
        module_identifiers = get_module_identifier_values(tree, const_dcl)
        module_comments = constants.setdefault(module_identifiers[-1], [])
        value = get_const_expr_value(const_expr)
        module_comments.append(
            Constant(get_first_identifier_value(const_dcl),
                     get_abstract_type_from_const_expr(const_type, value),
                     value))

    typedefs = {}
    typedef_dcls = tree.find_data('typedef_dcl')
    for typedef_dcl in typedef_dcls:
        assert len(typedef_dcl.children) == 1
        child = typedef_dcl.children[0]
        assert 'type_declarator' == child.data
        assert len(child.children) == 2
        abstract_type = get_abstract_type(child.children[0])
        child = child.children[1]
        assert 'any_declarators' == child.data
        assert len(child.children) == 1, 'Only support single typedefs atm'
        child = child.children[0]
        identifier = get_first_identifier_value(child)
        abstract_type = get_abstract_type_optionally_as_array(
            abstract_type, child)
        if identifier in typedefs:
            assert typedefs[identifier] == abstract_type
        else:
            typedefs[identifier] = abstract_type

    struct_defs = list(tree.find_data('struct_def'))
    if len(struct_defs) == 1:
        msg = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[0]),
                               name=get_child_identifier_value(
                                   struct_defs[0]))))
        annotations = get_annotations(struct_defs[0])
        msg.structure.annotations += annotations
        add_message_members(msg, struct_defs[0])
        resolve_typedefed_names(msg.structure, typedefs)
        constant_module_name = msg.structure.namespaced_type.name + \
            CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            msg.constants += constants[constant_module_name]
        content.elements.append(msg)

    elif len(struct_defs) == 2:
        request = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[0]),
                               name=get_child_identifier_value(
                                   struct_defs[0]))))
        assert request.structure.namespaced_type.name.endswith(
            SERVICE_REQUEST_MESSAGE_SUFFIX)
        add_message_members(request, struct_defs[0])
        resolve_typedefed_names(request.structure, typedefs)
        constant_module_name = \
            request.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            request.constants += constants[constant_module_name]

        response = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[1]),
                               name=get_child_identifier_value(
                                   struct_defs[1]))))
        assert response.structure.namespaced_type.name.endswith(
            SERVICE_RESPONSE_MESSAGE_SUFFIX)
        add_message_members(response, struct_defs[1])
        resolve_typedefed_names(response.structure, typedefs)
        constant_module_name = \
            response.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            response.constants += constants[constant_module_name]

        assert request.structure.namespaced_type.namespaces == \
            response.structure.namespaced_type.namespaces
        request_basename = request.structure.namespaced_type.name[:-len(
            SERVICE_REQUEST_MESSAGE_SUFFIX)]
        response_basename = response.structure.namespaced_type.name[:-len(
            SERVICE_RESPONSE_MESSAGE_SUFFIX)]
        assert request_basename == response_basename

        srv = Service(
            NamespacedType(
                namespaces=request.structure.namespaced_type.namespaces,
                name=request_basename), request, response)
        content.elements.append(srv)

    elif len(struct_defs) == 3:
        goal = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[0]),
                               name=get_child_identifier_value(
                                   struct_defs[0]))))
        assert goal.structure.namespaced_type.name.endswith(ACTION_GOAL_SUFFIX)
        add_message_members(goal, struct_defs[0])
        resolve_typedefed_names(goal.structure, typedefs)
        constant_module_name = \
            goal.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            goal.constants += constants[constant_module_name]

        result = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[1]),
                               name=get_child_identifier_value(
                                   struct_defs[1]))))
        assert result.structure.namespaced_type.name.endswith(
            ACTION_RESULT_SUFFIX)
        add_message_members(result, struct_defs[1])
        resolve_typedefed_names(result.structure, typedefs)
        constant_module_name = \
            result.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            result.constants += constants[constant_module_name]

        assert goal.structure.namespaced_type.namespaces == \
            result.structure.namespaced_type.namespaces
        goal_basename = goal.structure.namespaced_type.name[:-len(
            ACTION_GOAL_SUFFIX)]
        result_basename = result.structure.namespaced_type.name[:-len(
            ACTION_RESULT_SUFFIX)]
        assert goal_basename == result_basename

        feedback_message = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[2]),
                               name=get_child_identifier_value(
                                   struct_defs[2]))))
        assert feedback_message.structure.namespaced_type.name.endswith(
            ACTION_FEEDBACK_SUFFIX)
        add_message_members(feedback_message, struct_defs[2])
        resolve_typedefed_names(feedback_message.structure, typedefs)
        constant_module_name = \
            feedback_message.structure.namespaced_type.name + \
            CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            feedback_message.constants += constants[constant_module_name]

        action = Action(
            NamespacedType(
                namespaces=goal.structure.namespaced_type.namespaces,
                name=goal_basename), goal, result, feedback_message)

        all_includes = content.get_elements_of_type(Include)
        unique_include_locators = {include.locator for include in all_includes}
        content.elements += [
            include for include in action.implicit_includes
            if include.locator not in unique_include_locators
        ]

        content.elements.append(action)

    else:
        assert False, \
            'Currently only .idl files with 1 (a message), 2 (a service) ' \
            'and 3 (an action) structures are supported'

    return content
Ejemplo n.º 4
0
def generate_py(generator_arguments_file, typesupport_impls):
    mapping = {
        '_idl.py.em': '_%s.py',
        '_idl_support.c.em': '_%s_s.c',
    }
    generate_files(generator_arguments_file, mapping)

    args = read_generator_arguments(generator_arguments_file)
    package_name = args['package_name']

    # expand init modules for each directory
    modules = {}
    idl_content = IdlContent()
    for idl_tuple in args.get('idl_tuples', []):
        idl_parts = idl_tuple.rsplit(':', 1)
        assert len(idl_parts) == 2

        idl_rel_path = pathlib.Path(idl_parts[1])
        idl_stems = modules.setdefault(str(idl_rel_path.parent), set())
        idl_stems.add(idl_rel_path.stem)

        locator = IdlLocator(*idl_parts)
        idl_file = parse_idl_file(locator)
        idl_content.elements += idl_file.content.elements

    # NOTE(sam): remove when a language specific name mangling is implemented

    def print_warning_if_reserved_keyword(member_name, interface_type,
                                          interface_name):
        if (keyword.iskeyword(member.name)):
            print("Member name '{}' in the {} '{}' is a "
                  'reserved keyword in Python and is not supported '
                  'at the moment. Please use a different name.'.format(
                      member_name, interface_type, interface_name),
                  file=sys.stderr)

    for message in idl_content.get_elements_of_type(Message):
        for member in message.structure.members:
            print_warning_if_reserved_keyword(
                member.name, 'message', message.structure.namespaced_type.name)

    for service in idl_content.get_elements_of_type(Service):
        for member in service.request_message.structure.members:
            print_warning_if_reserved_keyword(member.name, 'service request',
                                              service.namespaced_type.name)
        for member in service.response_message.structure.members:
            print_warning_if_reserved_keyword(member.name, 'service response',
                                              service.namespaced_type.name)

    for action in idl_content.get_elements_of_type(Action):
        for member in action.goal.structure.members:
            print_warning_if_reserved_keyword(member.name, 'action goal',
                                              action.namespaced_type.name)
        for member in action.feedback.structure.members:
            print_warning_if_reserved_keyword(member.name, 'action feedback',
                                              action.namespaced_type.name)
        for member in action.result.structure.members:
            print_warning_if_reserved_keyword(member.name, 'action result',
                                              action.namespaced_type.name)

    for subfolder in modules.keys():
        with open(os.path.join(args['output_dir'], subfolder, '__init__.py'),
                  'w') as f:
            for idl_stem in sorted(modules[subfolder]):
                module_name = '_' + \
                    convert_camel_case_to_lower_case_underscore(idl_stem)
                f.write(
                    f'from {package_name}.{subfolder}.{module_name} import '
                    f'{idl_stem}  # noqa: F401\n')

    # expand templates per available typesupport implementation
    template_dir = args['template_dir']
    type_support_impl_by_filename = {
        '_%s_s.ep.{0}.c'.format(impl): impl
        for impl in typesupport_impls
    }
    mapping_msg_pkg_extension = {
        os.path.join(template_dir, '_idl_pkg_typesupport_entry_point.c.em'):
        type_support_impl_by_filename.keys(),
    }

    for template_file in mapping_msg_pkg_extension.keys():
        assert os.path.exists(
            template_file), 'Could not find template: ' + template_file

    latest_target_timestamp = get_newest_modification_time(
        args['target_dependencies'])

    for template_file, generated_filenames in mapping_msg_pkg_extension.items(
    ):
        for generated_filename in generated_filenames:
            package_name = args['package_name']
            data = {
                'package_name':
                args['package_name'],
                'content':
                idl_content,
                'typesupport_impl':
                type_support_impl_by_filename.get(generated_filename, ''),
            }
            generated_file = os.path.join(args['output_dir'],
                                          generated_filename % package_name)
            expand_template(template_file,
                            data,
                            generated_file,
                            minimum_timestamp=latest_target_timestamp)

    return 0
Ejemplo n.º 5
0
def extract_content_from_ast(tree):
    content = IdlContent()

    include_directives = tree.find_data('include_directive')
    for include_directive in include_directives:
        assert len(include_directive.children) == 1
        child = include_directive.children[0]
        assert child.data in ('h_char_sequence', 'q_char_sequence')
        include_token = next(child.scan_values(_find_tokens(None)))
        content.elements.append(Include(include_token.value))

    const_dcls = tree.find_data('const_dcl')
    for const_dcl in const_dcls:
        const_type = next(const_dcl.find_data('const_type'))
        const_expr = next(const_dcl.find_data('const_expr'))
        content.elements.append(
            Constant(get_first_identifier_value(const_dcl),
                     get_abstract_type_from_const_expr(const_type),
                     get_const_expr_value(const_expr)))

    typedefs = {}
    typedef_dcls = tree.find_data('typedef_dcl')
    for typedef_dcl in typedef_dcls:
        assert len(typedef_dcl.children) == 1
        child = typedef_dcl.children[0]
        assert 'type_declarator' == child.data
        assert len(child.children) == 2
        abstract_type = get_abstract_type(child.children[0])
        child = child.children[1]
        assert 'any_declarators' == child.data
        assert len(child.children) == 1, 'Only support single typedefs atm'
        child = child.children[0]
        identifier = get_first_identifier_value(child)
        abstract_type = get_abstract_type_optionally_as_array(
            abstract_type, child)
        if identifier in typedefs:
            assert typedefs[identifier] == abstract_type
        else:
            typedefs[identifier] = abstract_type

    struct_defs = list(tree.find_data('struct_def'))
    if len(struct_defs) == 1:
        msg = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[0]),
                               name=get_first_identifier_value(
                                   struct_defs[0]))))
        add_message_members(msg, struct_defs[0])
        resolve_typedefed_names(msg.structure, typedefs)
        # TODO move "global" constants/enums within a "matching" namespace into the message
        msg.constants.update(
            {c.name: c
             for c in content.elements if isinstance(c, Constant)})
        # msg.constants.update(constants)
        content.elements.append(msg)

    elif len(struct_defs) == 2:
        request = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[0]),
                               name=get_first_identifier_value(
                                   struct_defs[0]))))
        assert request.structure.type.name.endswith(
            SERVICE_REQUEST_MESSAGE_SUFFIX)
        add_message_members(request, struct_defs[0])
        resolve_typedefed_names(request.structure, typedefs)
        # TODO move "global" constants/enums within a "matching" namespace into the request message

        response = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[1]),
                               name=get_first_identifier_value(
                                   struct_defs[1]))))
        assert response.structure.type.name.endswith(
            SERVICE_RESPONSE_MESSAGE_SUFFIX)
        add_message_members(response, struct_defs[1])
        resolve_typedefed_names(response.structure, typedefs)
        # TODO move "global" constants/enums within a "matching" namespace into the response msg

        assert request.structure.type.namespaces == \
            response.structure.type.namespaces
        request_basename = request.structure.type.name[:-len(
            SERVICE_REQUEST_MESSAGE_SUFFIX)]
        response_basename = response.structure.type.name[:-len(
            SERVICE_RESPONSE_MESSAGE_SUFFIX)]
        assert request_basename == response_basename

        srv = Service(
            NamespacedType(namespaces=request.structure.type.namespaces,
                           name=request_basename), request, response)
        content.elements.append(srv)

    elif len(struct_defs) == 3:
        goal_request = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[0]),
                               name=get_first_identifier_value(
                                   struct_defs[0]))))
        assert goal_request.structure.type.name.endswith(
            ACTION_GOAL_SERVICE_SUFFIX + SERVICE_REQUEST_MESSAGE_SUFFIX)
        add_message_members(goal_request, struct_defs[0])
        resolve_typedefed_names(goal_request.structure, typedefs)
        # TODO move "global" constants/enums within a "matching" namespace into
        # the goal request message

        result_response = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[1]),
                               name=get_first_identifier_value(
                                   struct_defs[1]))))
        assert result_response.structure.type.name.endswith(
            ACTION_RESULT_SERVICE_SUFFIX + SERVICE_RESPONSE_MESSAGE_SUFFIX)
        add_message_members(result_response, struct_defs[1])
        resolve_typedefed_names(result_response.structure, typedefs)
        # TODO move "global" constants/enums within a "matching" namespace into
        # the result response message

        assert goal_request.structure.type.namespaces == \
            result_response.structure.type.namespaces
        goal_request_basename = goal_request.structure.type.name[:-len(
            ACTION_GOAL_SERVICE_SUFFIX + SERVICE_REQUEST_MESSAGE_SUFFIX)]
        result_response_basename = result_response.structure.type.name[:-len(
            ACTION_RESULT_SERVICE_SUFFIX + SERVICE_RESPONSE_MESSAGE_SUFFIX)]
        assert goal_request_basename == result_response_basename

        feedback_message = Message(
            Structure(
                NamespacedType(namespaces=get_module_identifier_values(
                    tree, struct_defs[2]),
                               name=get_first_identifier_value(
                                   struct_defs[2]))))
        assert feedback_message.structure.type.name.endswith(
            ACTION_FEEDBACK_MESSAGE_SUFFIX)
        add_message_members(feedback_message, struct_defs[2])
        resolve_typedefed_names(feedback_message.structure, typedefs)
        # TODO move "global" constants/enums within a "matching" namespace into
        # the feedback message

        action = Action(
            NamespacedType(namespaces=goal_request.structure.type.namespaces,
                           name=goal_request_basename), goal_request,
            result_response, feedback_message)
        content.elements.append(action)

    else:
        assert False, \
            'Currently only .idl files with 1 (a message), 2 (a service) ' \
            'and 3 (an action) structures are supported'

    return content
Ejemplo n.º 6
0
def generate_rs(generator_arguments_file, typesupport_impls):
    args = read_generator_arguments(generator_arguments_file)
    package_name = args['package_name']

    # expand init modules for each directory
    modules = {}
    idl_content = IdlContent()
    dependency_packages = set()

    (Path(args['output_dir']) / 'rust/src').mkdir(parents=True, exist_ok=True)

    for dep_tuple in args.get('ros_interface_dependencies', []):
        dep_parts = dep_tuple.rsplit(':', 1)
        assert len(dep_parts) == 2
        if dep_parts[0] != package_name:
            dependency_packages.add(dep_parts[0])

    for idl_tuple in args.get('idl_tuples', []):
        idl_parts = idl_tuple.rsplit(':', 1)
        assert len(idl_parts) == 2

        idl_rel_path = pathlib.Path(idl_parts[1])
        idl_stems = modules.setdefault(str(idl_rel_path.parent), set())
        idl_stems.add(idl_rel_path.stem)

        locator = IdlLocator(*idl_parts)
        idl_file = parse_idl_file(locator)
        idl_content.elements += idl_file.content.elements

    typesupport_impls = typesupport_impls.split(';')

    template_dir = args['template_dir']

    mapping_msgs = {
        os.path.join(template_dir, 'msg.rs.em'): ['rust/src/%s.rs'],
    }

    mapping_srvs = {
        os.path.join(template_dir, 'srv.rs.em'): ['rust/src/%s.rs'],
    }

    # Ensure the required templates exist
    for template_file in mapping_msgs.keys():
        assert os.path.exists(template_file), \
            'Messages template file %s not found' % template_file
    for template_file in mapping_srvs.keys():
        assert os.path.exists(template_file), \
            'Services template file %s not found' % template_file

    data = {
        'get_rmw_rs_type': make_get_rmw_rs_type(args['package_name']),
        'get_rs_name': get_rs_name,
        'get_idiomatic_rs_type':
        make_get_idiomatic_rs_type(args['package_name']),
        'constant_value_to_rs': constant_value_to_rs,
        'value_to_rs': value_to_rs,
        'convert_camel_case_to_lower_case_underscore':
        convert_camel_case_to_lower_case_underscore,
        'convert_lower_case_underscore_to_camel_case':
        convert_lower_case_underscore_to_camel_case,
        'msg_specs': [],
        'srv_specs': [],
        'package_name': args['package_name'],
        'typesupport_impls': typesupport_impls,
    }

    latest_target_timestamp = get_newest_modification_time(
        args['target_dependencies'])

    for message in idl_content.get_elements_of_type(Message):
        data['msg_specs'].append(('msg', message))

    for service in idl_content.get_elements_of_type(Service):
        data['srv_specs'].append(('srv', service))

    if data['msg_specs']:
        for template_file, generated_filenames in mapping_msgs.items():
            for generated_filename in generated_filenames:
                generated_file = os.path.join(args['output_dir'],
                                              generated_filename % 'msg')
                expand_template(os.path.join(template_dir, template_file),
                                data.copy(),
                                generated_file,
                                minimum_timestamp=latest_target_timestamp)

    if data['srv_specs']:
        for template_file, generated_filenames in mapping_srvs.items():
            for generated_filename in generated_filenames:
                generated_file = os.path.join(args['output_dir'],
                                              generated_filename % 'srv')
                expand_template(os.path.join(template_dir, template_file),
                                data.copy(),
                                generated_file,
                                minimum_timestamp=latest_target_timestamp)

    expand_template(os.path.join(template_dir, 'lib.rs.em'),
                    data.copy(),
                    os.path.join(args['output_dir'], 'rust/src/lib.rs'),
                    minimum_timestamp=latest_target_timestamp)

    cargo_toml_data = {
        'dependency_packages': dependency_packages,
        'package_name': args['package_name'],
        'package_version': args['package_version'],
    }
    expand_template(os.path.join(template_dir, 'Cargo.toml.em'),
                    cargo_toml_data,
                    os.path.join(args['output_dir'], 'rust/Cargo.toml'),
                    minimum_timestamp=latest_target_timestamp)

    expand_template(os.path.join(template_dir, 'build.rs.em'), {},
                    os.path.join(args['output_dir'], 'rust/build.rs'),
                    minimum_timestamp=latest_target_timestamp)

    return 0
Ejemplo n.º 7
0
def generate_py(generator_arguments_file, typesupport_impls):
    mapping = {
        '_idl.py.em': '_%s.py',
        '_idl_support.c.em': '_%s_s.c',
    }
    generate_files(generator_arguments_file, mapping)

    args = read_generator_arguments(generator_arguments_file)
    package_name = args['package_name']

    # expand init modules for each directory
    modules = {}
    idl_content = IdlContent()
    for idl_tuple in args.get('idl_tuples', []):
        idl_parts = idl_tuple.rsplit(':', 1)
        assert len(idl_parts) == 2

        idl_rel_path = pathlib.Path(idl_parts[1])
        idl_stems = modules.setdefault(str(idl_rel_path.parent), set())
        idl_stems.add(idl_rel_path.stem)

        locator = IdlLocator(*idl_parts)
        idl_file = parse_idl_file(locator)
        idl_content.elements += idl_file.content.elements

    for subfolder in modules.keys():
        with open(os.path.join(args['output_dir'], subfolder, '__init__.py'),
                  'w') as f:
            for idl_stem in sorted(modules[subfolder]):
                module_name = '_' + \
                    convert_camel_case_to_lower_case_underscore(idl_stem)
                f.write('from {package_name}.{subfolder}.{module_name} import '
                        '{idl_stem}  # noqa: F401\n'.format_map(locals()))

    # expand templates per available typesupport implementation
    template_dir = args['template_dir']
    type_support_impl_by_filename = {
        '_%s_s.ep.{0}.c'.format(impl): impl
        for impl in typesupport_impls
    }
    mapping_msg_pkg_extension = {
        os.path.join(template_dir, '_idl_pkg_typesupport_entry_point.c.em'):
        type_support_impl_by_filename.keys(),
    }

    for template_file in mapping_msg_pkg_extension.keys():
        assert os.path.exists(
            template_file), 'Could not find template: ' + template_file

    latest_target_timestamp = get_newest_modification_time(
        args['target_dependencies'])

    for template_file, generated_filenames in mapping_msg_pkg_extension.items(
    ):
        for generated_filename in generated_filenames:
            package_name = args['package_name']
            data = {
                'package_name':
                args['package_name'],
                'content':
                idl_content,
                'typesupport_impl':
                type_support_impl_by_filename.get(generated_filename, ''),
            }
            generated_file = os.path.join(args['output_dir'],
                                          generated_filename % package_name)
            expand_template(template_file,
                            data,
                            generated_file,
                            minimum_timestamp=latest_target_timestamp)

    return 0
Ejemplo n.º 8
0
def extract_content_from_ast(tree):
    content = IdlContent()

    include_directives = tree.find_data('include_directive')
    for include_directive in include_directives:
        assert len(include_directive.children) == 1
        child = include_directive.children[0]
        assert child.data in ('h_char_sequence', 'q_char_sequence')
        include_token = next(child.scan_values(_find_tokens(None)))
        content.elements.append(Include(include_token.value))

    constants = {}
    const_dcls = tree.find_data('const_dcl')
    for const_dcl in const_dcls:
        const_type = next(const_dcl.find_data('const_type'))
        const_expr = next(const_dcl.find_data('const_expr'))
        module_identifiers = get_module_identifier_values(tree, const_dcl)
        module_comments = constants.setdefault(
            module_identifiers[-1], [])
        value = get_const_expr_value(const_expr)
        module_comments.append(Constant(
            get_first_identifier_value(const_dcl),
            get_abstract_type_from_const_expr(const_type, value),
            value))

    typedefs = {}
    typedef_dcls = tree.find_data('typedef_dcl')
    for typedef_dcl in typedef_dcls:
        assert len(typedef_dcl.children) == 1
        child = typedef_dcl.children[0]
        assert 'type_declarator' == child.data
        assert len(child.children) == 2
        abstract_type = get_abstract_type(child.children[0])
        child = child.children[1]
        assert 'any_declarators' == child.data
        assert len(child.children) == 1, 'Only support single typedefs atm'
        child = child.children[0]
        identifier = get_first_identifier_value(child)
        abstract_type = get_abstract_type_optionally_as_array(
            abstract_type, child)
        if identifier in typedefs:
            assert typedefs[identifier] == abstract_type
        else:
            typedefs[identifier] = abstract_type

    struct_defs = list(tree.find_data('struct_def'))
    if len(struct_defs) == 1:
        msg = Message(Structure(NamespacedType(
            namespaces=get_module_identifier_values(tree, struct_defs[0]),
            name=get_child_identifier_value(struct_defs[0]))))
        annotations = get_annotations(struct_defs[0])
        msg.structure.annotations += annotations
        add_message_members(msg, struct_defs[0])
        resolve_typedefed_names(msg.structure, typedefs)
        constant_module_name = msg.structure.namespaced_type.name + \
            CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            msg.constants += constants[constant_module_name]
        content.elements.append(msg)

    elif len(struct_defs) == 2:
        request = Message(Structure(NamespacedType(
            namespaces=get_module_identifier_values(tree, struct_defs[0]),
            name=get_child_identifier_value(struct_defs[0]))))
        assert request.structure.namespaced_type.name.endswith(
            SERVICE_REQUEST_MESSAGE_SUFFIX)
        add_message_members(request, struct_defs[0])
        resolve_typedefed_names(request.structure, typedefs)
        constant_module_name = \
            request.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            request.constants += constants[constant_module_name]

        response = Message(Structure(NamespacedType(
            namespaces=get_module_identifier_values(tree, struct_defs[1]),
            name=get_child_identifier_value(struct_defs[1]))))
        assert response.structure.namespaced_type.name.endswith(
            SERVICE_RESPONSE_MESSAGE_SUFFIX)
        add_message_members(response, struct_defs[1])
        resolve_typedefed_names(response.structure, typedefs)
        constant_module_name = \
            response.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            response.constants += constants[constant_module_name]

        assert request.structure.namespaced_type.namespaces == \
            response.structure.namespaced_type.namespaces
        request_basename = request.structure.namespaced_type.name[
            :-len(SERVICE_REQUEST_MESSAGE_SUFFIX)]
        response_basename = response.structure.namespaced_type.name[
            :-len(SERVICE_RESPONSE_MESSAGE_SUFFIX)]
        assert request_basename == response_basename

        srv = Service(
            NamespacedType(
                namespaces=request.structure.namespaced_type.namespaces,
                name=request_basename),
            request, response)
        content.elements.append(srv)

    elif len(struct_defs) == 3:
        goal = Message(Structure(NamespacedType(
            namespaces=get_module_identifier_values(tree, struct_defs[0]),
            name=get_child_identifier_value(struct_defs[0]))))
        assert goal.structure.namespaced_type.name.endswith(ACTION_GOAL_SUFFIX)
        add_message_members(goal, struct_defs[0])
        resolve_typedefed_names(goal.structure, typedefs)
        constant_module_name = \
            goal.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            goal.constants += constants[constant_module_name]

        result = Message(Structure(NamespacedType(
            namespaces=get_module_identifier_values(tree, struct_defs[1]),
            name=get_child_identifier_value(struct_defs[1]))))
        assert result.structure.namespaced_type.name.endswith(
            ACTION_RESULT_SUFFIX)
        add_message_members(result, struct_defs[1])
        resolve_typedefed_names(result.structure, typedefs)
        constant_module_name = \
            result.structure.namespaced_type.name + CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            result.constants += constants[constant_module_name]

        assert goal.structure.namespaced_type.namespaces == \
            result.structure.namespaced_type.namespaces
        goal_basename = goal.structure.namespaced_type.name[
            :-len(ACTION_GOAL_SUFFIX)]
        result_basename = result.structure.namespaced_type.name[
            :-len(ACTION_RESULT_SUFFIX)]
        assert goal_basename == result_basename

        feedback_message = Message(Structure(NamespacedType(
            namespaces=get_module_identifier_values(tree, struct_defs[2]),
            name=get_child_identifier_value(struct_defs[2]))))
        assert feedback_message.structure.namespaced_type.name.endswith(
            ACTION_FEEDBACK_SUFFIX)
        add_message_members(feedback_message, struct_defs[2])
        resolve_typedefed_names(feedback_message.structure, typedefs)
        constant_module_name = \
            feedback_message.structure.namespaced_type.name + \
            CONSTANT_MODULE_SUFFIX
        if constant_module_name in constants:
            feedback_message.constants += constants[constant_module_name]

        action = Action(
            NamespacedType(
                namespaces=goal.structure.namespaced_type.namespaces,
                name=goal_basename),
            goal, result, feedback_message)

        all_includes = content.get_elements_of_type(Include)
        unique_include_locators = {
            include.locator for include in all_includes}
        content.elements += [
            include for include in action.implicit_includes
            if include.locator not in unique_include_locators]

        content.elements.append(action)

    else:
        assert False, \
            'Currently only .idl files with 1 (a message), 2 (a service) ' \
            'and 3 (an action) structures are supported'

    return content