From ea4a1731986b7f420c31f978edc7219edde448be Mon Sep 17 00:00:00 2001 From: JackLivio Date: Wed, 1 Aug 2018 14:06:34 -0400 Subject: Add support for mandatory and removed versioning --- tools/InterfaceGenerator/MsgVersionGenerate.py | 34 +++++- tools/InterfaceGenerator/generator/Model.py | 50 +++++++-- .../generator/generators/SmartFactoryBase.py | 45 ++++++-- .../generator/parsers/RPCBase.py | 119 ++++++++++++++++++++- 4 files changed, 219 insertions(+), 29 deletions(-) (limited to 'tools/InterfaceGenerator') diff --git a/tools/InterfaceGenerator/MsgVersionGenerate.py b/tools/InterfaceGenerator/MsgVersionGenerate.py index 86251cd419..4a24a3239f 100644 --- a/tools/InterfaceGenerator/MsgVersionGenerate.py +++ b/tools/InterfaceGenerator/MsgVersionGenerate.py @@ -12,14 +12,25 @@ def generate_msg_version(file_name, path_to_storage): """ tree = xml.etree.ElementTree.parse(file_name) root = tree.getroot() - if (root.tag == "interface" and "version" in root.attrib): + if (root.tag == "interface" and "version" and "minVersion" in root.attrib): check_version_format(root.attrib["version"]) array = (root.attrib["version"]).split(".") major_version = array[0] minor_version = array[1] patch_version = array[2] - if (major_version.isdigit() and minor_version.isdigit() and patch_version.isdigit): - data_for_storage = prepare_data_for_storage(major_version, minor_version, patch_version) + + check_minimum_version_format(root.attrib["minVersion"]) + minimum_version_array = (root.attrib["minVersion"]).split(".") + if (len(minimum_version_array) == 2): + minimum_version_array.append("0") + minimum_major_version = minimum_version_array[0] + minimum_minor_version = minimum_version_array[1] + minimum_patch_version = minimum_version_array[2] + + if (major_version.isdigit() and minor_version.isdigit() and patch_version.isdigit() and + minimum_major_version.isdigit() and minimum_minor_version.isdigit() and minimum_patch_version.isdigit()): + data_for_storage = prepare_data_for_storage(major_version, minor_version, patch_version, + minimum_major_version, minimum_minor_version, minimum_patch_version) store_data_to_file(path_to_storage, data_for_storage) else: raise RPCBase.ParseError("Attribute version has incorect value in MOBILE_API.xml") @@ -45,7 +56,16 @@ def check_version_format(version): raise RPCBase.ParseError("Incorrect format of version please check MOBILE_API.xml. " "Need format of version major_version.minor_version.patch_version") -def prepare_data_for_storage(major_version, minor_version, patch_version): + +def check_minimum_version_format(version): + """Checks correctness of format of version + """ + p = re.compile('\d+\\.\d+\\.\d+|\d+\\.\d+') + result = p.match(version) + if result == None or (result.end() != len(version)): + raise RPCBase.ParseError("Incorrect format of version please check MOBILE_API.xml. " + "Need format of minVersion major_version.minor_version or major_version.minor_version.patch_version") +def prepare_data_for_storage(major_version, minor_version, patch_version, minimum_major_version, minimum_minor_version, minimum_patch_version): """Prepares data to store to file. """ temp = Template( @@ -80,8 +100,12 @@ def prepare_data_for_storage(major_version, minor_version, patch_version): u'''const uint16_t major_version = $m_version;\n''' u'''const uint16_t minor_version = $min_version;\n''' u'''const uint16_t patch_version = $p_version;\n''' + u'''const uint16_t minimum_major_version = $min_major_version;\n''' + u'''const uint16_t minimum_minor_version = $min_minor_version;\n''' + u'''const uint16_t minimum_patch_version = $min_patch_version;\n''' u'''} // namespace application_manager\n''' u'''#endif // GENERATED_MSG_VERSION_H''') - data_to_file = temp.substitute(m_version = major_version, min_version = minor_version, p_version = patch_version) + data_to_file = temp.substitute(m_version = major_version, min_version = minor_version, p_version = patch_version, + min_major_version = minimum_major_version, min_minor_version = minimum_minor_version, min_patch_version = minimum_patch_version) return data_to_file diff --git a/tools/InterfaceGenerator/generator/Model.py b/tools/InterfaceGenerator/generator/Model.py index ee458d934a..c4d2eca0bd 100755 --- a/tools/InterfaceGenerator/generator/Model.py +++ b/tools/InterfaceGenerator/generator/Model.py @@ -124,7 +124,8 @@ class InterfaceItemBase(object): """ def __init__(self, name, description=None, design_description=None, - issues=None, todos=None, platform=None, default_value=None, scope=None): + issues=None, todos=None, platform=None, default_value=None, scope=None, + since=None, until=None, deprecated=None, removed=None): self.name = name self.description = description if description is not None else [] self.design_description = \ @@ -134,6 +135,10 @@ class InterfaceItemBase(object): self.platform = platform self.default_value = default_value self.scope = scope + self.since = since + self.until = until + self.deprecated = deprecated + self.removed = removed class EnumElement(InterfaceItemBase): @@ -149,13 +154,18 @@ class EnumElement(InterfaceItemBase): def __init__(self, name, description=None, design_description=None, issues=None, todos=None, platform=None, internal_name=None, - value=None): + value=None, since=None, until=None, deprecated=None, removed=None): super(EnumElement, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, platform=platform) self.internal_name = internal_name self.value = value + self.since = since + self.until = until + self.deprecated = deprecated + self.removed = removed + @property def primary_name(self): @@ -180,7 +190,7 @@ class Enum(InterfaceItemBase): def __init__(self, name, description=None, design_description=None, issues=None, todos=None, platform=None, internal_scope=None, - elements=None, scope=None): + elements=None, scope=None, since=None, until=None, deprecated=None, removed=None): super(Enum, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, @@ -189,6 +199,10 @@ class Enum(InterfaceItemBase): self.internal_scope = internal_scope self.elements = \ elements if elements is not None else collections.OrderedDict() + self.since = since + self.until = until + self.deprecated = deprecated + self.removed = removed class EnumSubset(InterfaceItemBase): @@ -204,7 +218,7 @@ class EnumSubset(InterfaceItemBase): def __init__(self, name, enum, description=None, design_description=None, issues=None, todos=None, platform=None, - allowed_elements=None): + allowed_elements=None, since=None, until=None, deprecated=None, removed=None): super(EnumSubset, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, @@ -213,6 +227,10 @@ class EnumSubset(InterfaceItemBase): self.enum = enum self.allowed_elements = \ allowed_elements if allowed_elements is not None else {} + self.since = since + self.until = until + self.deprecated = deprecated + self.removed = removed class Param(InterfaceItemBase): @@ -229,7 +247,8 @@ class Param(InterfaceItemBase): def __init__(self, name, param_type, description=None, design_description=None, issues=None, todos=None, - platform=None, is_mandatory=True, default_value=None, scope=None): + platform=None, is_mandatory=True, default_value=None, scope=None, + since=None, until=None, deprecated=None, removed=None): super(Param, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, @@ -238,6 +257,10 @@ class Param(InterfaceItemBase): self.is_mandatory = is_mandatory self.param_type = param_type self.default_value = default_value + self.since = since + self.until = until + self.deprecated = deprecated + self.removed=removed class FunctionParam(Param): @@ -251,11 +274,13 @@ class FunctionParam(Param): def __init__(self, name, param_type, description=None, design_description=None, issues=None, todos=None, - platform=None, is_mandatory=True, default_value=None, scope=None): + platform=None, is_mandatory=True, default_value=None, scope=None, + since=None, until=None, deprecated=None, removed=None): super(FunctionParam, self).__init__( name, param_type=param_type, description=description, design_description=design_description, issues=issues, todos=todos, - platform=platform, is_mandatory=is_mandatory, default_value=default_value, scope=scope) + platform=platform, is_mandatory=is_mandatory, default_value=default_value, + scope=scope, since=since, until=until, deprecated=deprecated, removed=removed) self.default_value = default_value @@ -270,12 +295,15 @@ class Struct(InterfaceItemBase): """ def __init__(self, name, description=None, design_description=None, - issues=None, todos=None, platform=None, members=None, scope=None): + issues=None, todos=None, platform=None, members=None, scope=None, + since=None, until=None, deprecated=None, removed=None): super(Struct, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, - platform=platform, scope=scope) + platform=platform, scope=scope, since=since, until=until, + deprecated=deprecated, removed=removed) + print since self.members = \ members if members is not None else collections.OrderedDict() @@ -293,11 +321,11 @@ class Function(InterfaceItemBase): def __init__(self, name, function_id, message_type, description=None, design_description=None, issues=None, todos=None, - platform=None, params=None, scope=None): + platform=None, params=None, scope=None, since=None, until=None, deprecated=None, removed=None): super(Function, self).__init__( name, description=description, design_description=design_description, issues=issues, todos=todos, - platform=platform, scope=scope) + platform=platform, scope=scope, since=None, until=None, deprecated=None, removed=None) self.function_id = function_id self.message_type = message_type diff --git a/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py index 0c500dee8e..05dd939ad0 100755 --- a/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py +++ b/tools/InterfaceGenerator/generator/generators/SmartFactoryBase.py @@ -505,7 +505,8 @@ class CodeGenerator(object): String with structs implementation source code. """ - + #print struct.name + #print struct.since processed_enums = [] return self._struct_impl_template.substitute( namespace=namespace, @@ -518,7 +519,7 @@ class CodeGenerator(object): schema_items_decl=self._gen_schema_items_decls( struct.members.values()), schema_item_fill=self._gen_schema_items_fill( - struct.members.values())), + struct.members.values(), struct.since, struct.until, struct.deprecated, struct.removed)), 1)) def _gen_schema_loc_decls(self, members, processed_enums): @@ -746,7 +747,7 @@ class CodeGenerator(object): return result - def _gen_schema_items_fill(self, members): + def _gen_schema_items_fill(self, members=None, since=None, until=None, deprecated=None, removed=None): """Generate schema items fill code. Generates source code that fills new schema with items. @@ -760,7 +761,7 @@ class CodeGenerator(object): """ result = u"\n".join( - [self._gen_schema_item_fill(x) for x in members]) + [self._gen_schema_item_fill(x, since, until, deprecated, removed) for x in members]) return u"".join([result, u"\n\n"]) if result else u"" @@ -781,7 +782,7 @@ class CodeGenerator(object): raise GenerateError("Unexpected call to the unimplemented function.") - def _gen_schema_item_fill(self, member): + def _gen_schema_item_fill(self, member, since, until, deprecated, removed): """Generate schema item fill code. Generates source code that fills new schema with item. @@ -793,11 +794,29 @@ class CodeGenerator(object): String with schema item fill code. """ - - return self._impl_code_item_fill_template.substitute( - name=member.name, - var_name=self._gen_schema_item_var_name(member), - is_mandatory=u"true" if member.is_mandatory is True else u"false") + #print(member.since) + #print member.name + if (since is not None or + until is not None or + deprecated is not None or + removed is not None or + member.since is not None or + member.until is not None or + member.deprecated is not None or + member.removed is not None): + return self._impl_code_item_fill_template_with_version.substitute( + name=member.name, + var_name=self._gen_schema_item_var_name(member), + is_mandatory=u"true" if member.is_mandatory is True else u"false", + since=member.since if member.since is not None else since if since is not None else "", + until=member.until if member.until is not None else until if until is not None else "", + deprecated=member.deprecated if member.deprecated is not None else deprecated if deprecated is not None else u"false", + removed=member.removed if member.removed is not None else removed if removed is not None else u"false") + else: + return self._impl_code_item_fill_template.substitute( + name=member.name, + var_name=self._gen_schema_item_var_name(member), + is_mandatory=u"true" if member.is_mandatory is True else u"false") @staticmethod def _gen_schema_item_var_name(member): @@ -899,7 +918,7 @@ class CodeGenerator(object): schema_items_decl=self._gen_schema_items_decls( function.params.values()), schema_item_fill=self._gen_schema_items_fill( - function.params.values()), + function.params.values(), function.since, function.until, function.deprecated, function.removed), schema_params_fill=self._gen_schema_params_fill( function.message_type.name)), 1)) @@ -1531,6 +1550,10 @@ class CodeGenerator(object): u'''schema_members["${name}"] = CObjectSchemaItem::''' u'''SMember(${var_name}, ${is_mandatory});''') + _impl_code_item_fill_template_with_version = string.Template( + u'''schema_members["${name}"] = CObjectSchemaItem::''' + u'''SMember(${var_name}, ${is_mandatory}, "${since}", "${until}", ${deprecated}, ${removed});''') + _function_impl_template = string.Template( u'''CSmartSchema $namespace::$class_name::''' u'''InitFunction_${function_id}_${message_type}(\n''' diff --git a/tools/InterfaceGenerator/generator/parsers/RPCBase.py b/tools/InterfaceGenerator/generator/parsers/RPCBase.py index 4853916dad..d3e103ce7a 100755 --- a/tools/InterfaceGenerator/generator/parsers/RPCBase.py +++ b/tools/InterfaceGenerator/generator/parsers/RPCBase.py @@ -6,7 +6,7 @@ Contains base parser for SDLRPC v1/v2 and JSON RPC XML format. import collections import xml.etree.ElementTree - +import re from generator import Model @@ -203,16 +203,35 @@ class Parser(object): internal_scope = None scope = None + since = None + until = None + deprecated = None + removed = None + result = None for attribute in attributes: if attribute == "internal_scope": internal_scope = attributes[attribute] elif attribute == "scope": scope = attributes[attribute] + elif attribute == "since": + result = self._parse_version(attributes[attribute]) + since = result + elif attribute == "until": + result = self._parse_version(attributes[attribute]) + until = result + elif attribute == "deprecated": + deprecated = attributes[attribute] + elif attribute == "removed": + removed = attributes[attribute] else: raise ParseError("Unexpected attribute '" + attribute + "' in enum '" + params["name"] + "'") params["internal_scope"] = internal_scope params["scope"] = scope + params["since"] = since + params["until"] = until + params["deprecated"] = deprecated + params["removed"] = removed elements = collections.OrderedDict() for subelement in subelements: @@ -236,13 +255,32 @@ class Parser(object): params, subelements, attrib = self._parse_base_item(element, prefix) scope = None + since = None + until = None + deprecated = None + removed = None + result = None for attribute in attrib: if attribute == "scope": scope = attrib[attribute] + elif attribute == "since": + result = self._parse_version(attrib[attribute]) + since = result + elif attribute == "until": + result = self._parse_version(attrib[attribute]) + until = result + elif attribute == "deprecated": + deprecated = attributes[attribute] + elif attribute == "removed": + removed = attrib[attribute] else: raise ParseError("Unexpected attribute '" + attribute + "' in struct '" + params["name"] + "'") params["scope"] = scope + params["since"] = since + params["until"] = until + params["deprecated"] = deprecated + params["removed"] = removed members = collections.OrderedDict() for subelement in subelements: @@ -271,13 +309,32 @@ class Parser(object): attributes) scope = None + since = None + until = None + deprecated = None + removed = None + result = None for attribute in attributes: if attribute == "scope": scope = attributes[attribute] + elif attribute == "since": + result = self._parse_version(attributes[attribute]) + since = result + elif attribute == "until": + result = self._parse_version(attributes[attribute]) + until = result + elif attribute == "deprecated": + deprecated = attributes[attribute] + elif attribute == "removed": + removed = attributes[attribute] params["function_id"] = function_id params["message_type"] = message_type params["scope"] = scope + params["since"] = since + params["until"] = until + params["deprecated"] = deprecated + params["removed"] = removed function_params = collections.OrderedDict() for subelement in subelements: @@ -443,6 +500,11 @@ class Parser(object): internal_name = None value = None + since = None + until = None + deprecated = None + removed = None + result = None for attribute in attributes: if attribute == "internal_name": internal_name = attributes[attribute] @@ -452,9 +514,22 @@ class Parser(object): except: raise ParseError("Invalid value for enum element: '" + attributes[attribute] + "'") + elif attribute == "since": + result = self._parse_version(attributes[attribute]) + since = result + elif attribute == "until": + result = self._parse_version(attributes[attribute]) + until = result + elif attribute == "deprecated": + deprecated = attributes[attribute] + elif attribute == "removed": + removed = attributes[attribute] params["internal_name"] = internal_name params["value"] = value - + params["since"] = since + params["until"] = until + params["deprecated"] = deprecated + params["removed"] = removed # Magic usage is correct # pylint: disable=W0142 return Model.EnumElement(**params) @@ -548,6 +623,27 @@ class Parser(object): """ params, subelements, attrib = self._parse_base_item(element, "") + since_version = self._extract_attrib(attrib, "since") + if since_version is not None: + result = self._parse_version(since_version) + params["since"] = result + + until_version = self._extract_attrib(attrib, "until") + if until_version is not None: + result = self._parse_version(until_version) + params["until"] = result + + deprecated = self._extract_attrib(attrib, "deprecated") + if deprecated is not None: + params["deprecated"] = deprecated + + removed = self._extract_attrib(attrib, "removed") + if removed is not None: + params["removed"] = removed + print("FOUND REMOVED!!!!!") + print(params["name"]) + + is_mandatory = self._extract_attrib(attrib, "mandatory") if is_mandatory is None: raise ParseError("'mandatory' is not specified for parameter '" + @@ -765,3 +861,22 @@ class Parser(object): print ("Ignoring attribute '" + name + "'") return True + + def _parse_version(self, version): + """ + Validates if a version supplied is in the correct + format of Major.Minor.Patch. If Major.Minor format + is supplied, a patch version of 0 will be added to + the end. + """ + p = re.compile('\d+\\.\d+\\.\d+|\d+\\.\d+') + result = p.match(version) + if result == None or (result.end() != len(version)): + raise RPCBase.ParseError("Incorrect format of version please check MOBILE_API.xml. " + "Need format of major_version.minor_version or major_version.minor_version.patch_version") + + version_array = version.split(".") + if (len(version_array) == 2): + version_array.append("0") + dot_str = "." + return dot_str.join(version_array) -- cgit v1.2.1