Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#203 SDL-0234 Proxy Library RPC Generation #202

Merged
merged 26 commits into from Feb 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e8db26b
Reverse engineer XSD from MOBILE_API.xml
vladmu Oct 29, 2019
61f261c
Add v6.0.0 compatible attributes into XSD
vladmu Oct 30, 2019
3e03b65
#203 SDL-0234 Proxy Library RPC Generation
vladmu Jan 13, 2020
9c35d2e
Update InterfaceParser/README.md
vladmu Jan 16, 2020
65a6ad7
Parser types section added
Jan 16, 2020
88719b5
Table markdown correction
Jan 16, 2020
1af08b5
refactoring according to comments in pull/202
o-mishch Jan 16, 2020
fab9035
updating markdown_generator to support command line arguments
o-mishch Jan 17, 2020
f410178
adding skip/overwrite feature to markdown
o-mishch Jan 20, 2020
341c9ee
delete SDLRPCV1 and JSONRPC parsers
o-mishch Jan 20, 2020
82e6847
delete SDLRPCV1 and JSONRPC parsers
o-mishch Jan 20, 2020
856154d
adding xsd validating
o-mishch Jan 20, 2020
dca8947
small refactoring as requested in code review
o-mishch Jan 20, 2020
25422e8
small refactoring as requested in code review
o-mishch Jan 20, 2020
8555a71
refactoring rpc_base, split it into some helper functions with descri…
o-mishch Jan 21, 2020
3839526
Update README.md
vladmu Jan 21, 2020
0b2833c
added Double string to extracting type
o-mishch Jan 21, 2020
13b091d
adding args.source_xsd into parse
o-mishch Jan 22, 2020
6049acd
adding args.source_xsd into parse
o-mishch Jan 22, 2020
693e572
rename ArgumentParser description
o-mishch Jan 22, 2020
a6c66df
adding manual handling
o-mishch Jan 22, 2020
b839688
minor fixes in markdown_generator
o-mishch Jan 27, 2020
451c2cc
minor fixes in markdown_generator
o-mishch Jan 28, 2020
0b3e66c
fix issue with hexvalue renaming
o-mishch Jan 28, 2020
a6dc295
wrap xml.etree.ElementTree.ParseError into parsers.parse_error.ParseE…
o-mishch Jan 29, 2020
8bda291
wrap XMLSchema exeption
o-mishch Jan 30, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
@@ -0,0 +1,10 @@
.idea
*.iml
*venv*
*.pyc
*out
.DS_Store
*htmlcov
*.coverage
*__pycache__
*.pytest_cache
136 changes: 136 additions & 0 deletions InterfaceParser/README.md
@@ -0,0 +1,136 @@
# Requirements

The parser requires Python 3.5 pre-installed in the system. This is the minimal Python 3 version that has not reached the end-of-life (https://devguide.python.org/devcycle/#end-of-life-branches).

The parser requires `xmlschema` library in order to provide the required schema validation. Additionally `pylint` and `coverage` libraries are required for unit tests.

Those libraries are described in `requirements.txt` and should be pre-installed by the command:
```shell script
pip install -r requirements.txt
```

# Parser types
Different parser types implemented in Interface Parser for parsing different types of source XML and generating the code in SDL_core project.

Parser | Source file
------ | ------
sdlrpcv1 | sdl_core/src/components/interfaces/v4_protocol_v1_2_no_extra.xml
sdlrpcv2 | sdl_core/src/components/interfaces/MOBILE_API.xml
jsonrpc | sdl_core/src/components/interfaces/HMI_API.xml
mobile-policy-types | sdl_core/src/components/interfaces/MOBILE_API.xml
hmi-policy-types | sdl_core/src/components/interfaces/HMI_API.xml

# `MOBILE_RPC.xml` structure
Jack-Byrne marked this conversation as resolved.
Show resolved Hide resolved

## Overview
This document contains the description of the `MOBILE_API.xml` structure in order of preparation specification and transformation rules for Proxy Library RPC Generation. This is not a full XML specification and only elements and attributes required for the code generation are described here. For the full specification see MOBILE_API.xsd.

## `<interface>`
The root element is the `<interface>`. The `<interface>` contains any number of `<enum>`, `<struct>` and `<function>`.

Example:
```xml
<interface name="string" version="string" minVersion="string" date="string">
<!--Zero or more repetitions:-->
<enum/>
<!--Zero or more repetitions:-->
<struct/>
<!--Zero or more repetitions:-->
<function/>
</interface>
```

## `<enum>`
The `<enum>` element contains any number of `<element>` that represents a set of possible values. The `<enum>` has a required `"name"` attribute.

Example:
```xml
<enum deprecated="boolean" internal_scope="string" name="string" platform="string" since="string" until="string">
<!--Zero or more repetitions:-->
<description>string</description>
<!--Zero or more repetitions:-->
<element hexvalue="string" internal_name="string" name="string" rootscreen="boolean" since="string" value="integer">
<!--Zero or more repetitions:-->
<description>string</description>
<!--Zero or more repetitions:-->
<warning>string</warning>
</element>
<!--Optional:-->
<history>
<enum/>
</history>
</enum>
```
SDL has two different enum types: `string` and `integer`. If `"hexvalue"` or `"value"` attribute exists, the enum type is `integer`, otherwise the enum type is `string`.

The `<element>` has a required `"name"` attribute. For `string` enums, the value of `"name"` attribute will be one of the possible values of the particular `<enum>`. For `integer` enums, the value of `"value"` attribute will be one of the possible values, the `"hexvalue"` is just a hexadecimal representation of the `"value"` attribute, any of them could be used but `"hexvalue"` is preferred if exist.

Additionally, `<element>` could have an `"internal_name"` attribute. This helper attribute is not used in communication with SDL Core and describes the `<element>` name for SDL libraries. The actual naming of `<element>` in libraries is per the following rationale: If the `<element>` has an `"internal_name"` attribute, all libraries should name the `<element>` based on this attribute. If `"internal_name"` is not specified, the libraries should name the `<element>` based on the `"name"` attribute. There are possible additional rules, e.g., for `internal_name="SamplingRate_8KHZ"` to cut the leading `<enum>` name, but those rules must be individually specified per each library.

## `<struct>`
The `<struct>` is a complex data type. The `<struct>` contains any number of `<param>`. The `<struct>` has a required `"name"` attribute.

Example:
```xml
<struct deprecated="boolean" name="string" since="string" until="string">
<!--Optional:-->
<history>
<struct/>
</history>
<!--Zero or more repetitions:-->
<description>string</description>
<!--Zero or more repetitions:-->
<param array="boolean" defvalue="integer|decimal|boolean|string" deprecated="boolean" mandatory="boolean" maxlength="integer" maxsize="integer" maxvalue="decimal" minlength="integer" minsize="integer" minvalue="decimal" name="string" since="string" type="string" until="string">
<!--Zero or more repetitions:-->
<description>string</description>
<!--Optional:-->
<history>
<param/>
</history>
</param>
</struct>
```
Each `<param>` requires `"name"`, `"type"` and `"mandatory"` attributes. The `"type"` attribute value should be one of `"Boolean"`, `"Float"`, `"Integer"`, `"String"` or the one of `<enum>`, `<struct>` name specified in the Mobile API.

Additionally, `<param>` could have `"array"` attribute to represent an array of values or objects of the described type. Attributes `"maxsize"` and `"minsize"` provide additional restrictions to an array.

Numeric types can be restricted using `"minvalue"` and `"maxvalue"`. The `"defvalue"` attribute contains default value with different type, depends on `<param>` type, note: this attribute is not allowed for `<struct>` type.

## `<function>`
The `<function>` element represents a specific RPC and message type of the Mobile API. It contains any number of `<param>`. The `<function>` has a required `"name"`, `"messagetype"`, `"functionID"` attributes.

Example:
```xml

<function deprecated="boolean" functionID="string" messagetype="string" name="string" since="string" until="string">
<!--Optional:-->
<history>
<function/>
</history>
<!--Zero or more repetitions:-->
<description>string</description>
<!--Zero or more repetitions:-->
<param array="boolean" defvalue="integer|decimal|boolean|string" deprecated="boolean" mandatory="boolean" maxlength="integer" maxsize="integer" maxvalue="decimal" minlength="integer" minsize="integer" minvalue="decimal" name="string" platform="string" since="string" type="string" until="string">
<!--Zero or more repetitions:-->
<description>string</description>
<!--Optional:-->
<history>
<param/>
</history>
<!--Zero or more repetitions:-->
<todo>string</todo>
<!--Zero or more repetitions:-->
<element name="string">
<!--Optional:-->
<description>string</description>
</element>
</param>
</function>
```
The `"messagetype"` attribute value should be one of `"request"`, `"response"`, or `"notification"`. The `"functionID"` attribute value should match the `"name`" attribute of one `<element>` of the `<enum>` named `"FunctionID"`.

Just like `<param>` elements in `<struct>`, each `<param>` has required `"name"`, `"type"`, and `"mandatory"` attributes. The `"type"` attribute value should be one of `"Boolean"`, `"Float"`, `"Integer"`, `"String"` or the one of `<enum>`, `<struct>` name exists in XML.

Additionally, `<param>` could have `"array"` attribute which means the param represents array of described types. Attributes `"max*"` and `"min*"` provide additional restrictions. The `"defvalue"` attribute contains default value with different type, depends on `<param>` type, note: this attribute is not allowed for `<struct>` type.

The `<param>` with `<enum>` type could additionally contain any number of `<element>` (but not more than the number of `<element>` in the related `<enum>`). The `<element>` has required `"name"` attribute and this should match the one of `<element>`'s `"name"` or `"internal_name"` attribute in the related `<enum>`. This restricts the represented value by the defined list of `<element>` instead of the full list of `<element>` in the related `<enum>`.
Empty file.
18 changes: 18 additions & 0 deletions InterfaceParser/model/array.py
@@ -0,0 +1,18 @@
"""Array type.

"""


class Array:
"""Array type.

:param min_size: minimum array size
:param max_size: maximum array size
:param element_type: type of array element

"""

def __init__(self, min_size=None, max_size=None, element_type=None):
self.min_size = min_size
self.max_size = max_size
self.element_type = element_type
14 changes: 14 additions & 0 deletions InterfaceParser/model/boolean.py
@@ -0,0 +1,14 @@
"""Boolean type.

"""


class Boolean:
"""Boolean type.

:param default_value: default value

"""

def __init__(self, default_value=None):
self.default_value = default_value
40 changes: 40 additions & 0 deletions InterfaceParser/model/enum.py
@@ -0,0 +1,40 @@
"""Enumeration.

"""
from collections import OrderedDict

from model.interface_item_base import InterfaceItemBase


class Enum(InterfaceItemBase):
"""Enumeration.

:param name: item name
:param description: list of string description elements
:param design_description: list of string design description elements
:param issues: list of issues
:param todos: list of string todo elements
:param platform: optional platform (string or None)
:param scope: optional scope: internal, partner or none (none by default, means public)
:param since: string that defines the rpc spec version an element was introduced
:param until: string that defines the rpc spec version an element was removed, deprecated, or changed
:param deprecated: boolean that defines if an element is planned to be removed in a future release
:param removed: boolean that defines if an element was removed from the api
:param history: array of api element signature changes

:param internal_scope: optional internal scope
:param elements: dictionary of enumeration elements (instances of EnumElement class)

"""

def __init__(self, name, description=None, design_description=None,
issues=None, todos=None, platform=None, internal_scope=None,
elements=None, scope=None, since=None, until=None,
deprecated=None, removed=None, history=None):
super(Enum, self).__init__(
name, description=description, design_description=design_description,
issues=issues, todos=todos, platform=platform, scope=scope,
Jack-Byrne marked this conversation as resolved.
Show resolved Hide resolved
since=since, until=until, deprecated=deprecated, removed=removed, history=history)

self.internal_scope = internal_scope
self.elements = elements if elements is not None else OrderedDict()
51 changes: 51 additions & 0 deletions InterfaceParser/model/enum_element.py
@@ -0,0 +1,51 @@
"""Element of enumeration.

"""

from model.interface_item_base import InterfaceItemBase


class EnumElement(InterfaceItemBase):
"""Element of enumeration.

:param name: item name
:param description: list of string description elements
:param design_description: list of string design description elements
:param issues: list of issues
:param todos: list of string todo elements
:param platform: optional platform (string or None)
:param since: string that defines the rpc spec version an element was introduced
:param until: string that defines the rpc spec version an element was removed, deprecated, or changed
:param deprecated: boolean that defines if an element is planned to be removed in a future release
:param removed: boolean that defines if an element was removed from the api
:param history: array of api element signature changes

:param internal_name: internal name of an element must be used by a
generator if it is provided (not None)
:param value: optional element value
:param hex_value: optional element hex value

"""

def __init__(self, name, description=None, design_description=None,
issues=None, todos=None, platform=None, internal_name=None,
value=None, hex_value=None, since=None, until=None,
deprecated=None, removed=None, history=None):
super(EnumElement, self).__init__(
name, description=description, design_description=design_description,
issues=issues, todos=todos, platform=platform, since=since,
until=until, deprecated=deprecated, removed=removed, history=history)

self.internal_name = internal_name
self.value = value
self.hex_value = hex_value

@property
def primary_name(self):
"""Primary name of the EnumElement.

Return the 'internal_name' property if presented or 'name' property
otherwise.

"""
return self.name if self.internal_name is None else self.internal_name
38 changes: 38 additions & 0 deletions InterfaceParser/model/enum_subset.py
@@ -0,0 +1,38 @@
"""Enumeration subset.

"""

from model.interface_item_base import InterfaceItemBase


class EnumSubset(InterfaceItemBase):
Jack-Byrne marked this conversation as resolved.
Show resolved Hide resolved
"""Enumeration subset.

:param name: item name
:param description: list of string description elements
:param design_description: list of string design description elements
:param issues: list of issues
:param todos: list of string todo elements
:param platform: optional platform (string or None)
:param since: string that defines the rpc spec version an element was introduced
:param until: string that defines the rpc spec version an element was removed, deprecated, or changed
:param deprecated: boolean that defines if an element is planned to be removed in a future release
:param removed: boolean that defines if an element was removed from the api
:param history: array of api element signature changes

:param enum: enumeration
:param allowed_elements: dictionary of elements of enumeration
which are allowed in this subset

"""

def __init__(self, name, enum, description=None, design_description=None,
issues=None, todos=None, platform=None, allowed_elements=None,
since=None, until=None, deprecated=None, removed=None, history=None):
super(EnumSubset, self).__init__(
name, description=description, design_description=design_description,
issues=issues, todos=todos, platform=platform,
since=since, until=until, deprecated=deprecated, removed=removed, history=history)

self.enum = enum
self.allowed_elements = allowed_elements if allowed_elements is not None else {}
18 changes: 18 additions & 0 deletions InterfaceParser/model/float.py
@@ -0,0 +1,18 @@
"""Floating-point type.

"""


class Float:
"""Floating-point type.

:param min_value: minimum allowed value
:param max_value: maximum allowed value
:param default_value: default value

"""

def __init__(self, min_value=None, max_value=None, default_value=None):
self.min_value = min_value
self.max_value = max_value
self.default_value = default_value
44 changes: 44 additions & 0 deletions InterfaceParser/model/function.py
@@ -0,0 +1,44 @@
"""Function.

"""

from collections import OrderedDict

from model.interface_item_base import InterfaceItemBase


class Function(InterfaceItemBase):
"""Function.

:param name: item name
:param description: list of string description elements
:param design_description: list of string design description elements
:param issues: list of issues
:param todos: list of string todo elements
:param platform: optional platform (string or None)
:param scope: optional scope: internal, partner or none (none by default, means public).
Note exists only in the hmi_api.xml
:param since: string that defines the rpc spec version an element was introduced
:param until: string that defines the rpc spec version an element was removed, deprecated, or changed
:param deprecated: boolean that defines if an element is planned to be removed in a future release
:param removed: boolean that defines if an element was removed from the api
:param history: array of api element signature changes

:param function_id: function identifier (EnumElement from Enum "FunctionID")
:param message_type: message type (EnumElement from Enum "messageType")
:param params: dictionary of function parameters (instances of FunctionParam class)

"""

def __init__(self, name, function_id, message_type, description=None,
design_description=None, issues=None, todos=None,
platform=None, params=None, scope=None, since=None, until=None, deprecated=None, removed=None,
history=None):
super(Function, self).__init__(
name, description=description, design_description=design_description,
issues=issues, todos=todos, platform=platform, scope=scope,
since=since, until=until, deprecated=deprecated, removed=removed, history=history)

self.function_id = function_id
self.message_type = message_type
self.params = params if params is not None else OrderedDict()
16 changes: 16 additions & 0 deletions InterfaceParser/model/integer.py
@@ -0,0 +1,16 @@
"""Integer type.

"""


class Integer:
"""Integer type.
:param min_value: minimum allowed value
:param max_value: maximum allowed value
:param default_value: default value
"""

def __init__(self, min_value=None, max_value=None, default_value=None):
self.min_value = min_value
self.max_value = max_value
self.default_value = default_value