示例#1
0
def _make_buildifier_command():
    """Returns a list starting with the buildifier executable, followed by any
    required default arguments."""
    return [
        find_data(_BUILDIFIER), "-add_tables={}".format(find_data(_TABLES))
    ]
示例#2
0
def generate_code(named_vector_filename,
                  include_prefix=None,
                  vector_hh_filename=None,
                  vector_cc_filename=None,
                  translator_hh_filename=None,
                  translator_cc_filename=None,
                  lcm_filename=None):

    cxx_include_path = os.path.dirname(named_vector_filename) + "/gen"
    if cxx_include_path.startswith("external/"):
        # Drake is being used from within a different workspace, so we have to
        # strip the "external/drake/" from the named_vector_filename.  (The
        # name after "external" will vary depending on what name the workspace
        # gave us, so we can't hard-code it to "drake".)
        cxx_include_path = "/".join(cxx_include_path.split("/")[2:])
    if include_prefix:
        cxx_include_path = os.path.join(include_prefix, cxx_include_path)
    snake, _ = os.path.splitext(os.path.basename(named_vector_filename))
    screaming_snake = snake.upper()
    camel = "".join([x.capitalize() for x in snake.split("_")])

    # Load the vector's details from protobuf.
    # In the future, this can be extended for nested messages.
    with open(named_vector_filename, "r") as f:
        vec = named_vector_pb2.NamedVector()
        google.protobuf.text_format.Merge(f.read(), vec)
        fields = [{
            'name': el.name,
            'doc': el.doc,
            'default_value': el.default_value,
            'doc_units': el.doc_units,
            'min_value': el.min_value,
            'max_value': el.max_value,
        } for el in vec.element]
        if vec.namespace:
            namespace_list = vec.namespace.split("::")
        else:
            namespace_list = []

    # Default some field attributes if they are missing.
    for item in fields:
        if len(item['default_value']) == 0:
            print("error: a default_value for {}.{} is required".format(
                snake, item['name']))
        if len(item['doc_units']) == 0:
            item['doc_units'] = DEFAULT_CTOR_FIELD_UNKNOWN_DOC_UNITS

    # The C++ namespace open & close dance is as requested in the protobuf.
    opening_namespace = "".join(
        ["namespace " + x + "{\n" for x in namespace_list])
    closing_namespace = "".join(
        ["}  // namespace " + x + "\n" for x in reversed(namespace_list)])

    # The context provides string substitutions for the C++ code blocks in the
    # literal strings throughout this program.
    context = dict()
    context.update(cxx_include_path=cxx_include_path)
    context.update(camel=camel)
    context.update(indices=camel + 'Indices')
    context.update(snake=snake)
    context.update(screaming_snake=screaming_snake)
    context.update(opening_namespace=opening_namespace)
    context.update(closing_namespace=closing_namespace)
    context.update(lcm_package="drake")

    # This is a specially-formatted code block to warn users not to edit.
    # This disclaimer text is special-cased by our review tool, reviewable.io.
    disclaimer = "// GENERATED FILE " + "DO NOT EDIT"
    context.update(generated_code_warning='\n'.join(
        [disclaimer, "// See drake/tools/lcm_vector_gen.py."]))

    cxx_names = []
    if vector_hh_filename:
        with open(vector_hh_filename, 'w') as hh:
            cxx_names.append(hh.name)
            put(hh, VECTOR_HH_PREAMBLE % context, 2)
            generate_indices(hh, context, fields)
            put(hh, '', 1)
            generate_indices_names_accessor_decl(hh, context)
            put(hh, VECTOR_CLASS_BEGIN % context, 2)
            generate_default_ctor(hh, context, fields)
            generate_set_to_named_variables(hh, context, fields)
            generate_do_clone(hh, context, fields)
            generate_accessors(hh, context, fields)
            put(hh, GET_COORDINATE_NAMES % context, 2)
            generate_is_valid(hh, context, fields)
            generate_calc_inequality_constraint(hh, context, fields)
            put(hh, VECTOR_CLASS_END % context, 2)
            put(hh, VECTOR_HH_POSTAMBLE % context, 1)

    if vector_cc_filename:
        with open(vector_cc_filename, 'w') as cc:
            cxx_names.append(cc.name)
            put(cc, VECTOR_CC_PREAMBLE % context, 2)
            generate_indices_storage(cc, context, fields)
            put(cc, '', 1)
            generate_indices_names_accessor_impl(cc, context, fields)
            put(cc, VECTOR_CC_POSTAMBLE % context, 1)

    if translator_hh_filename:
        with open(translator_hh_filename, 'w') as hh:
            cxx_names.append(hh.name)
            put(hh, TRANSLATOR_HH_PREAMBLE % context, 2)
            put(hh, TRANSLATOR_CLASS_DECL % context, 2)
            put(hh, TRANSLATOR_HH_POSTAMBLE % context, 1)

    if translator_cc_filename:
        with open(translator_cc_filename, 'w') as cc:
            cxx_names.append(cc.name)
            put(cc, TRANSLATOR_CC_PREAMBLE % context, 2)
            generate_allocate_output_vector(cc, context, fields)
            generate_deserialize(cc, context, fields)
            generate_serialize(cc, context, fields)
            put(cc, TRANSLATOR_CC_POSTAMBLE % context, 1)

    if lcm_filename:
        with open(lcm_filename, 'w') as lcm:
            put(lcm, LCMTYPE_PREAMBLE % context, 2)
            for field in fields:
                put(lcm, "  double {};  // {}".format(field['name'],
                                                      field['doc']), 1)
            put(lcm, LCMTYPE_POSTAMBLE % context, 1)

    if cxx_names:
        # Run clang-format over all C++ files.  Inserting a .clang-format
        # settings file is problematic when formatting within bazel-genfiles,
        # so instead we pass its contents on the command line.
        with open(find_data(".clang-format"), "r") as f:
            yaml_data = yaml.load(f, Loader=yaml.Loader)
            style = str(yaml_data)
            # For some reason, clang-format really wants lowercase booleans.
            style = style.replace("False", "false").replace("True", "true")
        subprocess.check_call(
            [get_clang_format_path(), "--style=" + style, "-i"] + cxx_names)
示例#3
0
def generate_code(
        named_vector_filename,
        include_prefix=None,
        vector_hh_filename=None,
        vector_cc_filename=None,
        translator_hh_filename=None,
        translator_cc_filename=None,
        lcm_filename=None):

    cxx_include_path = os.path.dirname(named_vector_filename) + "/gen"
    if cxx_include_path.startswith("external/"):
        # Drake is being used from within a different workspace, so we have to
        # strip the "external/drake/" from the named_vector_filename.  (The
        # name after "external" will vary depending on what name the workspace
        # gave us, so we can't hard-code it to "drake".)
        cxx_include_path = "/".join(cxx_include_path.split("/")[2:])
    if include_prefix:
        cxx_include_path = os.path.join(include_prefix, cxx_include_path)
    snake, _ = os.path.splitext(os.path.basename(named_vector_filename))
    screaming_snake = snake.upper()
    camel = "".join([x.capitalize() for x in snake.split("_")])

    # Load the vector's details from protobuf.
    # In the future, this can be extended for nested messages.
    with open(named_vector_filename, "r") as f:
        vec = named_vector_pb2.NamedVector()
        google.protobuf.text_format.Merge(f.read(), vec)
        fields = [{
            'name': el.name,
            'doc': el.doc,
            'default_value': el.default_value,
            'doc_units': el.doc_units,
            'min_value': el.min_value,
            'max_value': el.max_value,
        } for el in vec.element]
        if vec.namespace:
            namespace_list = vec.namespace.split("::")
        else:
            namespace_list = []

    # Default some field attributes if they are missing.
    for item in fields:
        if len(item['default_value']) == 0:
            print("error: a default_value for {}.{} is required".format(
                snake, item['name']))
        if len(item['doc_units']) == 0:
            item['doc_units'] = DEFAULT_CTOR_FIELD_UNKNOWN_DOC_UNITS

    # The C++ namespace open & close dance is as requested in the protobuf.
    opening_namespace = "".join(["namespace " + x + "{\n"
                                 for x in namespace_list])
    closing_namespace = "".join(["}  // namespace " + x + "\n"
                                 for x in reversed(namespace_list)])

    # The context provides string substitutions for the C++ code blocks in the
    # literal strings throughout this program.
    context = dict()
    context.update(cxx_include_path=cxx_include_path)
    context.update(camel=camel)
    context.update(indices=camel + 'Indices')
    context.update(snake=snake)
    context.update(screaming_snake=screaming_snake)
    context.update(opening_namespace=opening_namespace)
    context.update(closing_namespace=closing_namespace)
    context.update(lcm_package="drake")

    # This is a specially-formatted code block to warn users not to edit.
    # This disclaimer text is special-cased by our review tool, reviewable.io.
    disclaimer = "// GENERATED FILE " + "DO NOT EDIT"
    context.update(generated_code_warning='\n'.join([
        disclaimer, "// See drake/tools/lcm_vector_gen.py."]))

    cxx_names = []
    if vector_hh_filename:
        with open(vector_hh_filename, 'w') as hh:
            cxx_names.append(hh.name)
            put(hh, VECTOR_HH_PREAMBLE % context, 2)
            generate_indices(hh, context, fields)
            put(hh, '', 1)
            generate_indices_names_accessor_decl(hh, context)
            put(hh, VECTOR_CLASS_BEGIN % context, 2)
            generate_default_ctor(hh, context, fields)
            generate_copy_and_assign(hh, context)
            generate_set_to_named_variables(hh, context, fields)
            generate_do_clone(hh, context, fields)
            generate_accessors(hh, context, fields)
            put(hh, GET_COORDINATE_NAMES % context, 2)
            generate_is_valid(hh, context, fields)
            generate_get_element_bounds(hh, context, fields)
            put(hh, VECTOR_CLASS_END % context, 2)
            put(hh, VECTOR_HH_POSTAMBLE % context, 1)

    if vector_cc_filename:
        with open(vector_cc_filename, 'w') as cc:
            cxx_names.append(cc.name)
            put(cc, VECTOR_CC_PREAMBLE % context, 2)
            generate_indices_storage(cc, context, fields)
            put(cc, '', 1)
            generate_indices_names_accessor_impl(cc, context, fields)
            put(cc, VECTOR_CC_POSTAMBLE % context, 1)

    if translator_hh_filename:
        with open(translator_hh_filename, 'w') as hh:
            cxx_names.append(hh.name)
            put(hh, TRANSLATOR_HH_PREAMBLE % context, 2)
            put(hh, TRANSLATOR_CLASS_DECL % context, 2)
            put(hh, TRANSLATOR_HH_POSTAMBLE % context, 1)

    if translator_cc_filename:
        with open(translator_cc_filename, 'w') as cc:
            cxx_names.append(cc.name)
            put(cc, TRANSLATOR_CC_PREAMBLE % context, 2)
            generate_allocate_output_vector(cc, context, fields)
            generate_deserialize(cc, context, fields)
            generate_serialize(cc, context, fields)
            put(cc, TRANSLATOR_CC_POSTAMBLE % context, 1)

    if lcm_filename:
        with open(lcm_filename, 'w') as lcm:
            put(lcm, LCMTYPE_PREAMBLE % context, 2)
            for field in fields:
                put(lcm, "  double {};  // {}".format(field['name'],
                                                      field['doc']), 1)
            put(lcm, LCMTYPE_POSTAMBLE % context, 1)

    if cxx_names:
        # Run clang-format over all C++ files.  Inserting a .clang-format
        # settings file is problematic when formatting within bazel-genfiles,
        # so instead we pass its contents on the command line.
        with open(find_data(".clang-format"), "r") as f:
            yaml_data = yaml.load(f, Loader=yaml.Loader)
            style = str(yaml_data)
            # For some reason, clang-format really wants lowercase booleans.
            style = style.replace("False", "false").replace("True", "true")
        subprocess.check_call(
            [get_clang_format_path(), "--style=" + style, "-i"] + cxx_names)
示例#4
0
def generate_code(
        named_vector_filename,
        vector_hh_filename=None,
        vector_cc_filename=None,
        translator_hh_filename=None,
        translator_cc_filename=None,
        lcm_filename=None):

    cxx_include_path = os.path.dirname(named_vector_filename) + "/gen"
    # TODO(#6996) Do this unconditionally once #6996 shuffle is finished.
    if not cxx_include_path.startswith("drake/"):
        # TODO(jwnimmer-tri) For use outside of Drake, this include_prefix
        # should probably be configurable, instead of hard-coded here.
        cxx_include_path = "drake/" + cxx_include_path
    snake, _ = os.path.splitext(os.path.basename(named_vector_filename))
    screaming_snake = snake.upper()
    camel = "".join([x.capitalize() for x in snake.split("_")])

    # Load the vector's details from protobuf.
    # In the future, this can be extended for nested messages.
    with open(named_vector_filename, "r") as f:
        vec = named_vector_pb2.NamedVector()
        google.protobuf.text_format.Merge(f.read(), vec)
        fields = [{
            'name': el.name,
            'doc': el.doc,
            'default_value': el.default_value,
            'doc_units': el.doc_units,
            'min_value': el.min_value,
            'max_value': el.max_value,
        } for el in vec.element]
        if vec.namespace:
            namespace_list = vec.namespace.split("::")
        else:
            namespace_list = []

    # Default some field attributes if they are missing.
    for item in fields:
        if len(item['default_value']) == 0:
            item['default_value'] = DEFAULT_CTOR_FIELD_DEFAULT_VALUE
        if len(item['doc_units']) == 0:
            item['doc_units'] = DEFAULT_CTOR_FIELD_UNKNOWN_DOC_UNITS

    # The C++ namespace open & close dance is as requested in the protobuf.
    opening_namespace = "".join(["namespace " + x + "{\n"
                                 for x in namespace_list])
    closing_namespace = "".join(["}  // namespace " + x + "\n"
                                 for x in reversed(namespace_list)])

    # The context provides string substitutions for the C++ code blocks in the
    # literal strings throughout this program.
    context = dict()
    context.update(cxx_include_path=cxx_include_path)
    context.update(camel=camel)
    context.update(indices=camel + 'Indices')
    context.update(snake=snake)
    context.update(screaming_snake=screaming_snake)
    context.update(opening_namespace=opening_namespace)
    context.update(closing_namespace=closing_namespace)
    context.update(lcm_package="drake")

    # This is a specially-formatted code block to warn users not to edit.
    # This disclaimer text is special-cased by our review tool, reviewable.io.
    disclaimer = "// GENERATED FILE " + "DO NOT EDIT"
    context.update(generated_code_warning='\n'.join([
        disclaimer, "// See drake/tools/lcm_vector_gen.py."]))

    cxx_names = []
    if vector_hh_filename:
        with open(vector_hh_filename, 'w') as hh:
            cxx_names.append(hh.name)
            put(hh, VECTOR_HH_PREAMBLE % context, 2)
            generate_indices(hh, context, fields)
            put(hh, '', 1)
            generate_indices_names_accessor_decl(hh, context)
            put(hh, VECTOR_CLASS_BEGIN % context, 2)
            generate_default_ctor(hh, context, fields)
            generate_do_clone(hh, context, fields)
            generate_accessors(hh, context, fields)
            put(hh, GET_COORDINATE_NAMES % context, 2)
            generate_is_valid(hh, context, fields)
            generate_calc_inequality_constraint(hh, context, fields)
            put(hh, VECTOR_CLASS_END % context, 2)
            put(hh, VECTOR_HH_POSTAMBLE % context, 1)

    if vector_cc_filename:
        with open(vector_cc_filename, 'w') as cc:
            cxx_names.append(cc.name)
            put(cc, VECTOR_CC_PREAMBLE % context, 2)
            generate_indices_storage(cc, context, fields)
            put(cc, '', 1)
            generate_indices_names_accessor_impl(cc, context, fields)
            put(cc, VECTOR_CC_POSTAMBLE % context, 1)

    if translator_hh_filename:
        with open(translator_hh_filename, 'w') as hh:
            cxx_names.append(hh.name)
            put(hh, TRANSLATOR_HH_PREAMBLE % context, 2)
            put(hh, TRANSLATOR_CLASS_DECL % context, 2)
            put(hh, TRANSLATOR_HH_POSTAMBLE % context, 1)

    if translator_cc_filename:
        with open(translator_cc_filename, 'w') as cc:
            cxx_names.append(cc.name)
            put(cc, TRANSLATOR_CC_PREAMBLE % context, 2)
            generate_allocate_output_vector(cc, context, fields)
            generate_deserialize(cc, context, fields)
            generate_serialize(cc, context, fields)
            put(cc, TRANSLATOR_CC_POSTAMBLE % context, 1)

    if lcm_filename:
        with open(lcm_filename, 'w') as lcm:
            put(lcm, LCMTYPE_PREAMBLE % context, 2)
            for field in fields:
                put(lcm, "  double {};  // {}".format(field['name'],
                                                      field['doc']), 1)
            put(lcm, LCMTYPE_POSTAMBLE % context, 1)

    # Run clang-format over all C++ files.
    for one_filename in cxx_names:
        # The clang-format tool has no way to specify a config file, other than
        # putting a dotfile somehwere in a parent dir of the target.  Because
        # our output is in genfiles but the dotfile is in runfiles, we won't
        # automatically find it.  We'll resolve that by temporarily symlinking
        # the dotfile into place.
        dotfile = find_data(".clang-format")
        temp_dotfile = os.path.join(
            os.path.dirname(one_filename), ".clang-format")
        assert not os.path.exists(temp_dotfile)
        os.symlink(dotfile, temp_dotfile)
        subprocess.check_call([
            get_clang_format_path(), "--style=file", "-i", one_filename])
        os.unlink(temp_dotfile)
示例#5
0
 def test_find(self):
     filename = find_data("tools/lint/test/find_data_test.txt")
     self.assertTrue(os.path.exists(filename))
     with open(filename, "r") as contents:
         lines = contents.readlines()
     self.assertListEqual(lines, ["Sample data for unit find_data_test.\n"])
示例#6
0
 def test_find(self):
     filename = find_data("tools/lint/test/find_data_test.txt")
     self.assertTrue(os.path.exists(filename))
     with open(filename, "r") as contents:
         lines = contents.readlines()
     self.assertListEqual(lines, ["Sample data for unit find_data_test.\n"])
示例#7
0
def _make_buildifier_command():
    """Returns a list starting with the buildifier executable, followed by any
    required default arguments."""
    return [
        find_data(_BUILDIFIER),
        "-add_tables={}".format(find_data(_TABLES))]