Skip to content

Commit

Permalink
Implement elements ValueList, SwValues
Browse files Browse the repository at this point in the history
  • Loading branch information
cogu committed Nov 3, 2023
1 parent da9112c commit c461f4a
Show file tree
Hide file tree
Showing 8 changed files with 540 additions and 48 deletions.
3 changes: 0 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.testing.unittestArgs": [
"-v",
"-s",
Expand All @@ -17,6 +15,5 @@
"--max-line-length=120",
"--ignore=D101,D102,D107,D200,D205,D400,D401"
],
"python.linting.flake8Enabled": false,
"python.analysis.typeCheckingMode": "off",
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ The name in the parenthesis after each element is the name used in the XML schem
* ArrayValueSpecification | ARRAY-VALUE-SPECIFICATION
* RecordValueSpecification | RECORD-VALUE-SPECIFICATION

#### XML - Data type elements

* ValueList | VALUE-LIST

#### XML - Calibration elements

* SwValues | AR:SW-VALUES
* ValueGroup | VALUE-GROUP

## [v0.5.0]

### Added
Expand Down
93 changes: 92 additions & 1 deletion src/autosar/xml/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ def __init__(self,
value_format: ar_enum.ValueFormat = ar_enum.ValueFormat.DEFAULT
) -> None:
self._value = self._validate_value(value)
if isinstance(value, str):
if value.startswith("0x"):
value_format = ar_enum.ValueFormat.HEXADECIMAL
elif value.startswith("0b"):
value_format = ar_enum.ValueFormat.BINARY
self.value_format = value_format

@property
Expand Down Expand Up @@ -1619,7 +1624,7 @@ def __init__(self, name: str,
self._assign_optional('offset', offset, float)


# Data type elements
# DataDictionary and DataType elements


class BaseType(ARElement):
Expand Down Expand Up @@ -2326,6 +2331,32 @@ def append(self, element: DataTypeMap) -> None:
raise TypeError(f'Unexpected type: "{str(type(element))}"')


class ValueList(ARObject):
"""
Complex-type AR:VALUE-LIST
Type: Concrete
Tag variants: 'SW-ARRAYSIZE'
"""

def __init__(self, values: list[int | float | NumericalValue] | None = None) -> None:
self.values = []
if values is not None:
if isinstance(values, (int, float)):
self.append(values)
else:
for value in values:
self.append(value)

def append(self, value: int | float | NumericalValue) -> None:
"""
Adds value to list of values
"""
if isinstance(value, (int, float, NumericalValue)):
self.values.append(value)
else:
raise TypeError(f"Invalid type for value: {str(type(value))}")


# Software address method (partly implemented)


Expand Down Expand Up @@ -2353,6 +2384,64 @@ def ref(self) -> SwAddrMethodRef:
value = '/'.join(reversed(ref_parts))
return SwAddrMethodRef(value)

# Calibration data


SwValueElement = Union[int, float, str, NumericalValue, "ValueGroup"] # Type alias


class SwValues(ARObject):
"""
Complex-type AR:SW-VALUES
Type: Concrete
Tag variants: SW-VALUES-PHYS
"""

def __init__(self,
values: list[SwValueElement] | None = None) -> None:
self.values = []
if values is not None:
if isinstance(values, (int, float, str, NumericalValue, ValueGroup)):
self.append(values)
elif isinstance(values, list):
for value in values:
self.append(value)

def append(self, value: SwValueElement) -> None:
"""
Appends value to list of values
XML elements not supported:
- VTF
- VF
"""
if isinstance(value, (int, float, str, NumericalValue, ValueGroup)):
self.values.append(value)
else:
raise TypeError(f"Invalid value type: {str(type(value))}")


class ValueGroup(SwValues):
"""
Complex-type AR:VALUE-GROUP
Type: Concrete
Tag variants: VG
"""

def __init__(self,
label: str | MultilanguageLongName | tuple[ar_enum.Language, str] | LanguageLongName | None = None,
values: SwValues | None = None) -> None:
self.label: MultilanguageLongName | None = None
super().__init__(values)
if label is not None:
if isinstance(label, MultilanguageLongName):
self.label = label
elif isinstance(label, (tuple, LanguageLongName)):
self.label = MultilanguageLongName(label)
else:
raise TypeError(f"Invalid type for 'label': {str(type(label))}")


# Constant and value specifications


Expand Down Expand Up @@ -2406,6 +2495,8 @@ def _make_from_args(cls, label: str | None,
return ValueSpecification._make_record_value_spefication(label, value[1:])
else:
raise ValueError(f"Invalid element type: {str(type(value[0]))}")
else:
raise TypeError(f"Invalid value type: {str(type(value))}")

@classmethod
def _make_array_value_spefication(cls, label: str | None, values: list) -> "ArrayValueSpecification":
Expand Down
7 changes: 3 additions & 4 deletions src/autosar/xml/enumeration.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,9 @@ class ValueFormat(Enum):

DEFAULT = 0 # Let Python decide the format
DECIMAL = 1
FLOAT = 2
HEXADECIMAL = 3
BINARY = 4
SCIENTIFIC = 5
HEXADECIMAL = 2
BINARY = 3
SCIENTIFIC = 4


########################################
Expand Down
87 changes: 84 additions & 3 deletions src/autosar/xml/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def __init__(self,
# CompuMethod
'COMPU-METHOD': self._read_compu_method,

# Data type elements
# DataType and DataDictionary elements
'APPLICATION-ARRAY-DATA-TYPE': self._read_application_array_data_type,
'APPLICATION-RECORD-DATA-TYPE': self._read_application_record_data_type,
'APPLICATION-PRIMITIVE-DATA-TYPE': self._read_application_primitive_data_type,
Expand All @@ -109,6 +109,7 @@ def __init__(self,
'IMPLEMENTATION-DATA-TYPE': self._read_implementation_data_type,
'DATA-TYPE-MAPPING-SET': self._read_data_type_mapping_set,


# Constraint elements
'DATA-CONSTR': self._read_data_constraint,

Expand Down Expand Up @@ -154,7 +155,7 @@ def __init__(self,
'INTERNAL-CONSTRS': self._read_internal_constraint,
'PHYS-CONSTRS': self._read_physical_constraint,
'DATA-CONSTR-RULE': self._read_data_constraint_rule,
# Data type elements
# DataType and DataDictionary elements
'BASE-TYPE-REF': self._read_sw_base_type_ref,
'SW-BIT-REPRESENTATION': self._read_sw_bit_representation,
'SW-DATA-DEF-PROPS-CONDITIONAL': self._read_sw_data_def_props_conditional,
Expand All @@ -164,7 +165,9 @@ def __init__(self,
'IMPLEMENTATION-DATA-TYPE-ELEMENT': self._read_implementation_data_type_element,
'APPLICATION-RECORD-ELEMENT': self._read_application_record_element,
'DATA-TYPE-MAP': self._read_data_type_map,

'SW-ARRAYSIZE': self._read_value_list,
# CalibrationData elements
'SW-VALUES-PHYS': self._read_sw_values,
# Reference elements
'PHYSICAL-DIMENSION-REF': self._read_physical_dimension_ref,
'APPLICATION-DATA-TYPE-REF': self._read_application_data_type_ref,
Expand Down Expand Up @@ -2003,6 +2006,25 @@ def _read_read_data_type_mapping_set_group(self, child_elements: ChildElementMap
data_type_maps.append(self._read_data_type_map(xml_data_type_map_element))
data["data_type_maps"] = data_type_maps

def _read_value_list(self, xml_element: ElementTree.Element) -> ar_element.ValueList:
"""
Reads complex-type AR:VALUE-LIST
Type: Concrete
Tag variants: 'SW-ARRAYSIZE'
"""
values = []
data = {"values": values}
for xml_value in xml_element.findall("./V"):
number = ar_element.NumericalValue(xml_value.text)
if number.value_format in (ar_enum.ValueFormat.HEXADECIMAL,
ar_enum.ValueFormat.BINARY,
ar_enum.ValueFormat.SCIENTIFIC):
values.append(number)
else:
values.append(number.value)
element = ar_element.ValueList(**data)
return element

# Constant and value specifications

def _read_text_value_specification(self,
Expand Down Expand Up @@ -2149,6 +2171,65 @@ def _read_value_specification_group(self, child_elements: ChildElementMap, data:
if xml_child is not None:
data["label"] = xml_child.text

# CalibrationData elements

def _read_sw_values(self,
xml_element: ElementTree.Element) -> ar_element.SwValues:
"""
Reads complex-type AR:SW-VALUES
Type: Concrete
Tag variants: 'SW-VALUES-PHYS'
"""
data = {}
child_elements = list(xml_element.findall("./*"))
self._read_sw_values_group(child_elements, data)
element = ar_element.SwValues(**data)
return element

def _read_sw_values_group(self,
xml_child_list: list[ElementTree.Element],
data: dict) -> None:
"""
Reads group AR:SW-VALUES
Type: Abstract
XML elements not supported:
- VTF
- VF
"""
values = []
data["values"] = values
for xml_child in xml_child_list:
if xml_child.tag == "VT":
values.append(xml_child.text)
elif xml_child.tag == "V":
number = ar_element.NumericalValue(xml_child.text)
if number.value_format in (ar_enum.ValueFormat.HEXADECIMAL,
ar_enum.ValueFormat.BINARY,
ar_enum.ValueFormat.SCIENTIFIC):
values.append(number)
else:
values.append(number.value)
elif xml_child.tag == "VG":
values.append(self._read_value_group(xml_child))
elif xml_child.tag in ("VTF", "VG"):
continue # Not supported, skip
else:
print(f"Unprocessed child element in VALUE-GROUP: <{xml_child.tag}>", file=sys.stderr)

def _read_value_group(self, xml_element: ElementTree.Element) -> ar_element.ValueGroup:
"""
Reads complex-type AR:VALUE-GROUP
"""
data = {}
child_elements = list(xml_element.findall("./*"))
if len(child_elements) > 0 and child_elements[0].tag == 'LABEL':
data["label"] = self._read_multi_language_long_name(child_elements.pop(0))
self._read_sw_values_group(child_elements, data)
element = ar_element.ValueGroup(**data)
return element

# UNFINISHED ELEMENTS - NEEDS REFACTORING

def _read_sender_receiver_interface(self, xml_element: ElementTree.Element) -> None:
Expand Down
Loading

0 comments on commit c461f4a

Please sign in to comment.