diff --git a/examples/xml/component/application_component.py b/examples/xml/component/application_component.py
index b97d49f..b296cb0 100644
--- a/examples/xml/component/application_component.py
+++ b/examples/xml/component/application_component.py
@@ -4,7 +4,6 @@
import os
import autosar
import autosar.xml.element as ar_element
-import autosar.xml.enumeration as ar_enum
def create_platform_types(packages: dict[str, ar_element.Package]):
@@ -50,17 +49,6 @@ def create_platform_types(packages: dict[str, ar_element.Package]):
packages["PlatformImplementationDataTypes"].append(uint32_impl_type)
-# def create_implementation_data_types(packages: dict[str, ar_element.Package]):
-# """
-# Creates non-platform implementation data types
-# """
-# sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref="AUTOSAR_Platform/BaseTypes/uint8")
-# inactive_active_t = ar_element.ImplementationDataType("InactiveActive_T",
-# category="VALUE",
-# sw_data_def_props=sw_data_def_props)
-# packages["ImplementationDataTypes"].append(inactive_active_t)
-
-
def create_sender_receiver_port_interfaces(packages: dict[str, ar_element.Package]):
"""
Create sender-receiver port interfaces used in example
@@ -69,9 +57,6 @@ def create_sender_receiver_port_interfaces(packages: dict[str, ar_element.Packag
port_interface = ar_element.SenderReceiverInterface("VehicleSpeed_I")
port_interface.create_data_element("VehicleSpeed", type_ref=uint16_impl_t.ref())
packages["PortInterfaces"].append(port_interface)
- port_interface = ar_element.SenderReceiverInterface("EngineSpeed_I")
- port_interface.create_data_element("EngineSpeed", type_ref=uint16_impl_t.ref())
- packages["PortInterfaces"].append(port_interface)
def create_client_server_interfaces(packages: dict[str, ar_element.Package]):
@@ -90,19 +75,37 @@ def create_client_server_interfaces(packages: dict[str, ar_element.Package]):
packages["PortInterfaces"].append(interface)
+def create_application_component(packages: dict[str, ar_element.Package]):
+ """
+ Creates application component with one sender-receiver port and one
+ client-server port
+ """
+ timer_interface = packages["PortInterfaces"].find("FreeRunningTimer_I")
+ vehicle_speed_interface = packages["PortInterfaces"].find("VehicleSpeed_I")
+ swc = ar_element.ApplicationSoftwareComponentType("MyApplication")
+ swc.create_require_port("VehicleSpeed", vehicle_speed_interface, com_spec={"init_value": 65535,
+ 'alive_timeout': 0,
+ 'enable_update': False,
+ 'uses_end_to_end_protection': False,
+ 'handle_never_received': False
+ })
+ swc.create_require_port("FreeRunningTimer", timer_interface)
+ packages["ComponentTypes"].append(swc)
+
+
def save_xml_files(workspace: autosar.xml.Workspace):
"""
Saves workspace as XML documents
"""
interface_document_path = os.path.abspath(os.path.join(os.path.dirname(
__file__), 'data', 'portinterfaces.arxml'))
- datatype_document_path = os.path.abspath(os.path.join(os.path.dirname(
- __file__), 'data', 'datatypes.arxml'))
platform_document_path = os.path.abspath(os.path.join(os.path.dirname(
__file__), 'data', 'platform.arxml'))
+ component_document_path = os.path.abspath(os.path.join(os.path.dirname(
+ __file__), 'data', 'MyApplication.arxml'))
workspace.create_document(interface_document_path, packages="/PortInterfaces")
- workspace.create_document(datatype_document_path, packages="/DataTypes")
workspace.create_document(platform_document_path, packages="/AUTOSAR_Platform")
+ workspace.create_document(component_document_path, packages="/ComponentTypes")
workspace.write_documents()
@@ -116,16 +119,19 @@ def main():
"PlatformDataConstraints",
"PlatformCompuMethods",
"ImplementationDataTypes",
- "PortInterfaces"],
+ "PortInterfaces",
+ "ComponentTypes"],
workspace.make_packages("AUTOSAR_Platform/BaseTypes",
"AUTOSAR_Platform/ImplementationDataTypes",
"AUTOSAR_Platform/DataConstraints",
"AUTOSAR_Platform/CompuMethods",
"DataTypes/ImplementationDataTypes",
- "PortInterfaces")))
+ "PortInterfaces",
+ "ComponentTypes")))
create_platform_types(packages)
create_sender_receiver_port_interfaces(packages)
create_client_server_interfaces(packages)
+ create_application_component(packages)
save_xml_files(workspace)
diff --git a/examples/xml/component/data/MyApplication.arxml b/examples/xml/component/data/MyApplication.arxml
new file mode 100644
index 0000000..3855af3
--- /dev/null
+++ b/examples/xml/component/data/MyApplication.arxml
@@ -0,0 +1,37 @@
+
+
+
+
+ ComponentTypes
+
+
+ MyApplication
+
+
+ VehicleSpeed
+
+
+ /PortInterfaces/VehicleSpeed_I/VehicleSpeed
+ false
+ 0
+ false
+ false
+
+
+ 65535
+
+
+
+
+ /PortInterfaces/VehicleSpeed_I
+
+
+ FreeRunningTimer
+ /PortInterfaces/FreeRunningTimer_I
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/xml/component/data/platform.arxml b/examples/xml/component/data/platform.arxml
new file mode 100644
index 0000000..72a93b4
--- /dev/null
+++ b/examples/xml/component/data/platform.arxml
@@ -0,0 +1,128 @@
+
+
+
+
+ AUTOSAR_Platform
+
+
+ BaseTypes
+
+
+ boolean
+ 8
+ BOOLEAN
+
+
+ uint8
+ 8
+
+
+ uint16
+ 16
+
+
+ uint32
+ 32
+
+
+
+
+ ImplementationDataTypes
+
+
+ boolean
+ VALUE
+
+
+
+ /AUTOSAR_Platform/BaseTypes/uint8
+ /AUTOSAR_Platform/CompuMethods/boolean_CompuMethod
+ /AUTOSAR_Platform/DataConstraints/boolean_DataConstr
+
+
+
+
+
+ uint8
+ VALUE
+
+
+
+ /AUTOSAR_Platform/BaseTypes/uint8
+
+
+
+
+
+ uint16
+ VALUE
+
+
+
+ /AUTOSAR_Platform/BaseTypes/uint16
+
+
+
+
+
+ uint32
+ VALUE
+
+
+
+ /AUTOSAR_Platform/BaseTypes/uint32
+
+
+
+
+
+
+
+ DataConstraints
+
+
+ boolean_DataConstr
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+ CompuMethods
+
+
+ boolean_CompuMethod
+ TEXTTABLE
+
+
+
+ FALSE
+ 0
+ 0
+
+ FALSE
+
+
+
+ TRUE
+ 1
+ 1
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/xml/component/data/portinterfaces.arxml b/examples/xml/component/data/portinterfaces.arxml
new file mode 100644
index 0000000..366b0e5
--- /dev/null
+++ b/examples/xml/component/data/portinterfaces.arxml
@@ -0,0 +1,54 @@
+
+
+
+
+ PortInterfaces
+
+
+ VehicleSpeed_I
+
+
+ VehicleSpeed
+ /AUTOSAR_Platform/ImplementationDataTypes/uint16
+
+
+
+
+ FreeRunningTimer_I
+
+
+ GetTime
+
+
+ value
+ /AUTOSAR_Platform/ImplementationDataTypes/uint32
+ OUT
+
+
+
+
+ IsTimerElapsed
+
+
+ startTime
+ /AUTOSAR_Platform/ImplementationDataTypes/uint32
+ IN
+
+
+ duration
+ /AUTOSAR_Platform/ImplementationDataTypes/uint32
+ IN
+
+
+ result
+ /AUTOSAR_Platform/ImplementationDataTypes/boolean
+ OUT
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/xml/port_interface/client_server_interface.py b/examples/xml/port_interface/client_server_interface.py
index 9aeba00..b5da46f 100644
--- a/examples/xml/port_interface/client_server_interface.py
+++ b/examples/xml/port_interface/client_server_interface.py
@@ -29,7 +29,7 @@ def create_platform_types(packages: dict[str, ar_element.Package]):
def create_port_interfaces(packages: dict[str, ar_element.Package]):
"""
- Creates interface with one element
+ Creates client-server interface with one operation
"""
uint32_impl_type = packages["PlatformImplementationDataTypes"].find("uint32")
interface = ar_element.ClientServerInterface("FreeRunningTimer_I", is_service=True)
diff --git a/src/autosar/xml/element.py b/src/autosar/xml/element.py
index 0afd477..84e12e6 100644
--- a/src/autosar/xml/element.py
+++ b/src/autosar/xml/element.py
@@ -20,13 +20,13 @@
# Type aliases
-ValueSpeficationElement = Union["TextValueSpecification",
- "NumericalValueSpecification",
- "NotAvailableValueSpecification",
- "ArrayValueSpecification",
- "RecordValueSpecification",
- "ApplicationValueSpecification",
- "ConstantReference"]
+ValueSpecificationElement = Union["TextValueSpecification",
+ "NumericalValueSpecification",
+ "NotAvailableValueSpecification",
+ "ArrayValueSpecification",
+ "RecordValueSpecification",
+ "ApplicationValueSpecification",
+ "ConstantReference"]
PortPrototypeElement = Union["ProvidePortPrototype",
"RequirePortPrototype",
@@ -449,8 +449,9 @@ class CompuMethodRef(BaseRef):
CompuMethod reference
"""
- def __init__(self, value: str) -> None:
- super().__init__(value, ar_enum.IdentifiableSubTypes.COMPU_METHOD)
+ def __init__(self, value: str,
+ dest: ar_enum.IdentifiableSubTypes = ar_enum.IdentifiableSubTypes.COMPU_METHOD) -> None:
+ super().__init__(value, dest)
def _accepted_subtypes(self) -> set[ar_enum.IdentifiableSubTypes]:
"""Acceptable values for dest"""
@@ -2202,6 +2203,15 @@ def __init__(self,
if ptr_target_props is not None:
self._set_attr_with_strict_type('ptr_target_props', ptr_target_props, SwPointerTargetProps)
+ @property
+ def is_queued(self) -> bool:
+ """
+ Returns True if impl_policy is set to QUEUED
+ """
+ if self.impl_policy is not None and self.impl_policy == ar_enum.SwImplPolicy.QUEUED:
+ return True
+ return False
+
class SwDataDefProps(ARObject):
"""
@@ -2455,10 +2465,10 @@ class VariableDataPrototype(AutosarDataPrototype):
def __init__(self,
name: str,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
**kwargs) -> None:
super().__init__(name, **kwargs)
- self.init_value: ValueSpeficationElement | None = None # .INIT-VALUE
+ self.init_value: ValueSpecificationElement | None = None # .INIT-VALUE
# .VARIATION-POINT not supported
self._assign_optional_strict("init_value", init_value, ValueSpecification)
@@ -2470,6 +2480,15 @@ def ref(self) -> VariableDataPrototypeRef | None:
ref_str = self._calc_ref_string()
return None if ref_str is None else VariableDataPrototypeRef(ref_str)
+ @property
+ def is_queued(self) -> bool:
+ """
+ Returns True if internal sw_data_def_props has its impl_policy is set to QUEUED
+ """
+ if self.sw_data_def_props is not None and len(self.sw_data_def_props.variants) > 0:
+ return self.sw_data_def_props.variants[0].is_queued
+ return False
+
class ParameterDataPrototype(AutosarDataPrototype):
"""
@@ -2480,10 +2499,10 @@ class ParameterDataPrototype(AutosarDataPrototype):
def __init__(self,
name: str,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
**kwargs) -> None:
super().__init__(name, **kwargs)
- self.init_value: ValueSpeficationElement | None = None # .INIT-VALUE
+ self.init_value: ValueSpecificationElement | None = None # .INIT-VALUE
# .VARIATION-POINT not supported
self._assign_optional_strict("init_value", init_value, ValueSpecification)
@@ -2919,7 +2938,31 @@ def __init__(self, label: str | None = None) -> None:
# .VARIATION-POINT not supported
@classmethod
- def make_value(cls, data: Any) -> ValueSpeficationElement:
+ def make_init_value(cls,
+ init_value: int | float | str | tuple | ValueSpecificationElement | None = None, # noqa E501 pylint: disable=C0301
+ init_value_ref: Union[str, ConstantRef, "ConstantReference", None] = None
+ ) -> ValueSpecificationElement:
+ """
+ Attempts to create an init value from either the init_value argument or init_value_ref.
+ Both cannot be set simultaneously
+ """
+ if init_value is not None:
+ if init_value_ref is not None:
+ msg = "init_value and init_value_ref cannot be set at the same time. One of them must be None"
+ raise ValueError(msg)
+ if isinstance(init_value, ValueSpecification):
+ return init_value
+ else:
+ return cls.make_value(init_value)
+ elif init_value_ref is not None:
+ if isinstance(init_value_ref, ConstantReference):
+ return init_value_ref
+ elif isinstance(init_value_ref, (str, ConstantRef)):
+ return ConstantReference(init_value_ref)
+ return None
+
+ @classmethod
+ def make_value(cls, data: Any) -> ValueSpecificationElement:
"""
Builds value specification based on Python data
Format 1 - data is not a tuple:
@@ -2961,7 +3004,7 @@ def make_value(cls, data: Any) -> ValueSpeficationElement:
@classmethod
def _make_from_args(cls, label: str | None,
value: Any,
- default_pattern: int | None = None) -> ValueSpeficationElement:
+ default_pattern: int | None = None) -> ValueSpecificationElement:
if isinstance(value, (int, float)):
return NumericalValueSpecification(label, value)
elif isinstance(value, str):
@@ -3047,10 +3090,10 @@ class ArrayValueSpecification(ValueSpecification):
def __init__(self,
label: str | None = None,
- elements: list[ValueSpeficationElement] | None = None
+ elements: list[ValueSpecificationElement] | None = None
) -> None:
super().__init__(label)
- self.elements: list[ValueSpeficationElement] = []
+ self.elements: list[ValueSpecificationElement] = []
if elements is not None:
if isinstance(elements, ValueSpecification):
self.append(elements)
@@ -3058,7 +3101,7 @@ def __init__(self,
for element in elements:
self.append(element)
- def append(self, element: ValueSpeficationElement):
+ def append(self, element: ValueSpecificationElement):
"""
Appends element to array specification
"""
@@ -3076,10 +3119,10 @@ class RecordValueSpecification(ValueSpecification):
def __init__(self,
label: str | None = None,
- fields: list[ValueSpeficationElement] | None = None
+ fields: list[ValueSpecificationElement] | None = None
) -> None:
super().__init__(label)
- self.fields: list[ValueSpeficationElement] = []
+ self.fields: list[ValueSpecificationElement] = []
if fields is not None:
if isinstance(fields, ValueSpecification):
self.append(fields)
@@ -3087,7 +3130,7 @@ def __init__(self,
for field in fields:
self.append(field)
- def append(self, field: ValueSpeficationElement):
+ def append(self, field: ValueSpecificationElement):
"""
Appends field to record specification
"""
@@ -3137,9 +3180,9 @@ class ConstantSpecification(ARElement):
Tag Variants: 'CONSTANT-SPECIFICATION'
"""
- def __init__(self, name: str, value: ValueSpeficationElement | None = None, **kwargs) -> None:
+ def __init__(self, name: str, value: ValueSpecificationElement | None = None, **kwargs) -> None:
super().__init__(name, **kwargs)
- self.value: ValueSpeficationElement = None # .VALUE-SPEC
+ self.value: ValueSpecificationElement = None # .VALUE-SPEC
if value is not None:
if isinstance(value, ValueSpecification):
self.value = value
@@ -3567,6 +3610,7 @@ def append_data_element(self, data_element: VariableDataPrototype):
Appends data element to internal list of elements
"""
if isinstance(data_element, VariableDataPrototype):
+ data_element.parent = self
self.data_elements.append(data_element)
else:
msg = f"data_element: Invalid type '{str(type(data_element))}'"
@@ -3584,7 +3628,7 @@ def append_invalidation_policy(self, invalidation_policy: InvalidationPolicy):
def create_data_element(self,
name: str,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
**kwargs) -> VariableDataPrototype:
"""
Convenience method for adding a new data element to this port interface
@@ -3657,7 +3701,7 @@ def append_data_element(self, nv_data: VariableDataPrototype):
def create_data_element(self,
name: str,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
**kwargs) -> VariableDataPrototype:
"""
Convenience method for adding a new data element to this port interface
@@ -3712,7 +3756,7 @@ def append_parameter(self, parameter: ParameterDataPrototype):
def create_parameter(self,
name: str,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
**kwargs) -> ParameterDataPrototype:
"""
Convenience method for adding a new parameter to this port interface
@@ -4156,6 +4200,43 @@ class ProvidePortComSpec(ARObject):
Group AR:P-PORT-COM-SPEC
"""
+ @classmethod
+ def make_from_port_interface(cls, port_interface: PortInterface, **kwargs) -> "ProvidePortComSpec":
+ """
+ Convenience method for creating require-port com-specs for port-interfaces
+ with one data element
+ Special keys for non-queued SenderReceiverInterface:
+ * init_value_ref: str | ConstantRef | ConstantReference
+ Remaining keys are the same as the constructor of NonqueuedSenderComSpec
+
+ Currently only supports SenderReceiverInterface
+ """
+ if isinstance(port_interface, SenderReceiverInterface):
+ if len(port_interface.data_elements) == 0:
+ raise ValueError(f"{port_interface.name}: Port interface must have at least one element")
+ if len(port_interface.data_elements) == 1:
+ data_element: VariableDataPrototype = port_interface.data_elements[0]
+ if data_element.is_queued:
+ return QueuedSenderComSpec(data_element_ref=data_element.ref(), **kwargs)
+ else:
+ return cls.make_non_queued_sender_com_spec(data_element_ref=data_element.ref(), **kwargs)
+ else:
+ raise NotImplementedError("Multiple data elements not yet supported")
+ else:
+ raise NotImplementedError(str(type(port_interface)))
+
+ @classmethod
+ def make_non_queued_sender_com_spec(cls,
+ init_value: int | float | str | tuple | ValueSpecificationElement | None = None, # noqa E501 pylint: disable=C0301
+ init_value_ref: str | ConstantRef | ConstantReference | None = None,
+ **kwargs
+ ) -> "NonqueuedSenderComSpec":
+ """
+ Convenience method for creating NonqueuedSenderComSpec
+ """
+ init_value = ValueSpecification.make_init_value(init_value, init_value_ref)
+ return NonqueuedSenderComSpec(init_value=init_value, **kwargs)
+
class SenderComSpec(ProvidePortComSpec):
"""
@@ -4251,12 +4332,12 @@ class NonqueuedSenderComSpec(SenderComSpec):
"""
def __init__(self,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
data_filter: DataFilter | None = None,
**kwargs) -> None:
super().__init__(**kwargs)
self.data_filter: DataFilter | None = None # .DATA-FILTER
- self.init_value: ValueSpeficationElement | None = None # .INIT-VALUE
+ self.init_value: ValueSpecificationElement | None = None # .INIT-VALUE
self._assign_optional_strict("data_filter", data_filter, DataFilter)
self._assign_optional_strict("init_value", init_value, ValueSpecification)
@@ -4269,12 +4350,12 @@ class NvProvideComSpec(ProvidePortComSpec):
def __init__(self,
variable_ref: VariableDataPrototypeRef | None = None,
- ram_block_init_value: ValueSpeficationElement | None = None,
- rom_block_init_value: ValueSpeficationElement | None = None,
+ ram_block_init_value: ValueSpecificationElement | None = None,
+ rom_block_init_value: ValueSpecificationElement | None = None,
) -> None:
super().__init__()
- self.ram_block_init_value: ValueSpeficationElement | None = None # .RAM-BLOCK-INIT-VALUE
- self.rom_block_init_value: ValueSpeficationElement | None = None # .RAM-BLOCK-INIT-VALUE
+ self.ram_block_init_value: ValueSpecificationElement | None = None # .RAM-BLOCK-INIT-VALUE
+ self.rom_block_init_value: ValueSpecificationElement | None = None # .RAM-BLOCK-INIT-VALUE
self.variable_ref: VariableDataPrototypeRef | None = None # .VARIABLE-REF
self._assign_optional_strict("ram_block_init_value", ram_block_init_value, ValueSpecification)
self._assign_optional_strict("rom_block_init_value", rom_block_init_value, ValueSpecification)
@@ -4289,10 +4370,10 @@ class ParameterProvideComSpec(ProvidePortComSpec):
def __init__(self,
parameter_ref: ParameterDataPrototypeRef | str | None = None,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
) -> None:
super().__init__()
- self.init_value: ValueSpeficationElement | None = None # .INIT-VALUE
+ self.init_value: ValueSpecificationElement | None = None # .INIT-VALUE
self.parameter_ref: VariableDataPrototypeRef | None = None # .PARAMETER-REF
self._assign_optional_strict("init_value", init_value, ValueSpecification)
self._assign_optional("parameter_ref", parameter_ref, ParameterDataPrototypeRef)
@@ -4369,6 +4450,43 @@ class RequirePortComSpec(ARObject):
Group AR:R-PORT-COM-SPEC
"""
+ @classmethod
+ def make_from_port_interface(cls, port_interface: PortInterface, **kwargs) -> "RequirePortComSpec":
+ """
+ Convenience method for creating require-port com-specs for port-interfaces
+ with one data element
+ Special keys for non-queued SenderReceiverInterface:
+ * init_value_ref: str | ConstantRef | ConstantReference
+ Remaining keys are the same as the constructor of NonqueuedReceiverComSpec
+
+ Currently only supports SenderReceiverInterface
+ """
+ if isinstance(port_interface, SenderReceiverInterface):
+ if len(port_interface.data_elements) == 0:
+ raise ValueError(f"{port_interface.name}: Port interface must have at least one element")
+ if len(port_interface.data_elements) == 1:
+ data_element: VariableDataPrototype = port_interface.data_elements[0]
+ if data_element.is_queued:
+ return QueuedReceiverComSpec(data_element_ref=data_element.ref(), **kwargs)
+ else:
+ return cls.make_non_queued_receiver_com_spec(data_element_ref=data_element.ref(), **kwargs)
+ else:
+ raise NotImplementedError("Multiple data elements not yet supported")
+ else:
+ raise NotImplementedError(str(type(port_interface)))
+
+ @classmethod
+ def make_non_queued_receiver_com_spec(cls,
+ init_value: int | float | str | tuple | ValueSpecificationElement | None = None, # noqa E501 pylint: disable=C0301
+ init_value_ref: str | ConstantRef | ConstantReference | None = None,
+ **kwargs
+ ) -> "NonqueuedReceiverComSpec":
+ """
+ Convenience method for creating NonqueuedReceiverComSpec
+ """
+ init_value = ValueSpecification.make_init_value(init_value, init_value_ref)
+ return NonqueuedReceiverComSpec(init_value=init_value, **kwargs)
+
class ReceiverComSpec(RequirePortComSpec):
"""
@@ -4475,8 +4593,8 @@ def __init__(self,
handle_data_status: bool | None = None,
handle_never_received: bool | None = None,
handle_timeout_type: ar_enum.HandleTimeout | None = None,
- init_value: ValueSpeficationElement | None = None,
- timeout_substitution_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
+ timeout_substitution_value: ValueSpecificationElement | None = None,
**kwargs) -> None:
super().__init__(**kwargs)
self.alive_timeout: int | float | None = None # .ALIVE-TIMEOUT
@@ -4485,8 +4603,8 @@ def __init__(self,
self.handle_data_status: bool | None = None # .HANDLE-DATA-STATUS
self.handle_never_received: bool | None = None # .HANDLE-NEVER-RECEIVED
self.handle_timeout_type: ar_enum.HandleTimeout | None = None # .HANDLE-TIMEOUT-TYPE
- self.init_value: ValueSpeficationElement | None = None # .INIT-VALUE
- self.timeout_substitution_value: ValueSpeficationElement | None = None # .TIMEOUT-SUBSTITUTION-VALUE
+ self.init_value: ValueSpecificationElement | None = None # .INIT-VALUE
+ self.timeout_substitution_value: ValueSpecificationElement | None = None # .TIMEOUT-SUBSTITUTION-VALUE
self._assign_optional("alive_timeout", alive_timeout, float)
self._assign_optional("enable_update", enable_update, bool)
self._assign_optional_strict("data_filter", data_filter, DataFilter)
@@ -4505,10 +4623,10 @@ class NvRequireComSpec(RequirePortComSpec):
def __init__(self,
variable_ref: VariableDataPrototypeRef | None = None,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
) -> None:
super().__init__()
- self.init_value: ValueSpeficationElement | None = None # .INIT-VALUE
+ self.init_value: ValueSpecificationElement | None = None # .INIT-VALUE
self.variable_ref: VariableDataPrototypeRef | None = None # .VARIABLE-REF
self._assign_optional_strict("init_value", init_value, ValueSpecification)
self._assign_optional("variable_ref", variable_ref, VariableDataPrototypeRef)
@@ -4522,10 +4640,10 @@ class ParameterRequireComSpec(RequirePortComSpec):
def __init__(self,
parameter_ref: ParameterDataPrototypeRef | str | None = None,
- init_value: ValueSpeficationElement | None = None,
+ init_value: ValueSpecificationElement | None = None,
) -> None:
super().__init__()
- self.init_value: ValueSpeficationElement | None = None # .INIT-VALUE
+ self.init_value: ValueSpecificationElement | None = None # .INIT-VALUE
self.parameter_ref: VariableDataPrototypeRef | None = None # .PARAMETER-REF
self._assign_optional_strict("init_value", init_value, ValueSpecification)
self._assign_optional("parameter_ref", parameter_ref, ParameterDataPrototypeRef)
@@ -4686,7 +4804,8 @@ def __init__(self,
for com_spec_elem in com_spec:
self.append_com_spec(com_spec_elem)
else:
- raise TypeError("com_spec must be of a type derived from RequirePortComSpec")
+ msg = "com_spec: Needs be of a type derived from RequirePortComSpec."
+ raise TypeError(msg + f" Got {str(type(com_spec))}")
def ref(self) -> PortPrototypeRef | None:
"""
@@ -4798,6 +4917,7 @@ def append_port(self, port: PortPrototypeElement):
Adds port to internal list of ports
"""
if isinstance(port, PortPrototype):
+ port.parent = self
self.ports.append(port)
else:
msg = "port type must be one of: ProvidePortPrototype, RequirePortPrototype, PRPortPrototype."
@@ -4866,6 +4986,51 @@ def ref(self) -> SwComponentTypeRef | None:
return None
return SwComponentTypeRef(ref_str, ar_enum.IdentifiableSubTypes.APPLICATION_SW_COMPONENT_TYPE)
+ def create_require_port(self,
+ name: str,
+ port_interface: PortInterface,
+ com_spec: dict | list[dict] | RequirePortComSpec | list[RequirePortComSpec] | None = None,
+ allow_unconnected: bool | None = None,
+ **kwargs) -> RequirePortPrototype:
+ """
+ Creates a new require port and adds it to the internal list of ports
+ """
+ if com_spec is not None:
+ if isinstance(com_spec, dict):
+ com_spec = RequirePortComSpec.make_from_port_interface(port_interface, **com_spec)
+ assert com_spec is not None
+ port = RequirePortPrototype(name, port_interface.ref(), com_spec, allow_unconnected, **kwargs)
+ self.append_port(port)
+ return port
+
+ def create_provide_port(self,
+ name: str,
+ port_interface: PortInterface | None = None,
+ com_spec: dict | list[dict] | ProvidePortComSpec | list[ProvidePortComSpec] | None = None,
+ **kwargs) -> ProvidePortPrototype:
+ """
+ Creates a new provide port and adds it to the internal list of ports
+ """
+ if com_spec is not None:
+ if isinstance(com_spec, dict):
+ com_spec = ProvidePortComSpec.make_from_port_interface(port_interface, **com_spec)
+ assert com_spec is not None
+ port = ProvidePortPrototype(name, port_interface.ref(), com_spec, **kwargs)
+ self.append_port(port)
+ return port
+
+ def create_pr_port(self,
+ name: str,
+ port_interface_ref: PortInterfaceRef | None = None,
+ com_spec: RequirePortComSpec | list[RequirePortComSpec] | None = None,
+ **kwargs) -> PRPortPrototype:
+ """
+ Creates a new pr-port and adds it to the internal list of ports
+ """
+ port = PRPortPrototype(name, port_interface_ref, com_spec, **kwargs)
+ self.append_port(port)
+ return port
+
class SwComponentPrototype(Identifiable):
"""
diff --git a/src/autosar/xml/reader.py b/src/autosar/xml/reader.py
index 0f78078..3166e3a 100644
--- a/src/autosar/xml/reader.py
+++ b/src/autosar/xml/reader.py
@@ -2651,7 +2651,7 @@ def _read_application_value_specification_group(self,
def _read_value_specification_element(self,
xml_element: ElementTree.Element
- ) -> ar_element.ValueSpeficationElement:
+ ) -> ar_element.ValueSpecificationElement:
"""
Reads any ValueSpecificationElement
"""
diff --git a/src/autosar/xml/writer.py b/src/autosar/xml/writer.py
index ac59e1a..28d9e5a 100644
--- a/src/autosar/xml/writer.py
+++ b/src/autosar/xml/writer.py
@@ -2303,7 +2303,7 @@ def _write_value_specification_group(self, elem: ar_element.ValueSpecification)
if elem.label is not None:
self._add_content("SHORT-LABEL", str(elem.label))
- def _write_value_specification_element(self, elem: ar_element.ValueSpeficationElement) -> None:
+ def _write_value_specification_element(self, elem: ar_element.ValueSpecificationElement) -> None:
"""
Switched writer for value specification elements
"""
diff --git a/tests/xml/test_software_component_builder.py b/tests/xml/test_software_component_builder.py
new file mode 100644
index 0000000..39df6e9
--- /dev/null
+++ b/tests/xml/test_software_component_builder.py
@@ -0,0 +1,167 @@
+"""Unit tests for programmatically building components and save them as XML"""
+
+# pylint: disable=missing-class-docstring, missing-function-docstring
+import os
+import sys
+import unittest
+from typing import Any
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../src')))
+import autosar.xml.element as ar_element # noqa E402
+import autosar # noqa E402
+
+
+def create_packages(workspace: autosar.xml.workspace.Workspace) -> dict[str, ar_element.Package]:
+ """
+ Creates the packages needed for unit tests
+ """
+ packages = dict(zip(["PlatformBaseTypes",
+ "PlatformImplementationDataTypes",
+ "PlatformDataConstraints",
+ "PlatformCompuMethods",
+ "Constants",
+ "PortInterfaces",
+ "ComponentTypes"],
+ workspace.make_packages("AUTOSAR_Platform/BaseTypes",
+ "AUTOSAR_Platform/ImplementationDataTypes",
+ "AUTOSAR_Platform/DataConstraints",
+ "AUTOSAR_Platform/CompuMethods",
+ "Constants",
+ "PortInterfaces",
+ "ComponentTypes")))
+ return packages
+
+
+def create_platform_types(packages: dict[str, ar_element.Package]):
+ """
+ Creates necessary platform types
+ """
+ boolean_base_type = ar_element.SwBaseType('boolean', size=8, encoding="BOOLEAN")
+ packages["PlatformBaseTypes"].append(boolean_base_type)
+ uint8_base_type = ar_element.SwBaseType('uint8', size=8)
+ packages["PlatformBaseTypes"].append(uint8_base_type)
+ uint16_base_type = ar_element.SwBaseType('uint16', size=16)
+ packages["PlatformBaseTypes"].append(uint16_base_type)
+ uint32_base_type = ar_element.SwBaseType('uint32', size=32)
+ packages["PlatformBaseTypes"].append(uint32_base_type)
+ boolean_data_constr = ar_element.DataConstraint.make_internal("boolean_DataConstr", 0, 1)
+ packages["PlatformDataConstraints"].append(boolean_data_constr)
+ computation = ar_element.Computation.make_value_table(["FALSE", "TRUE"])
+ boolean_compu_method = ar_element.CompuMethod(name="boolean_CompuMethod",
+ category="TEXTTABLE",
+ int_to_phys=computation)
+ packages["PlatformCompuMethods"].append(boolean_compu_method)
+ sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref(),
+ data_constraint_ref=boolean_data_constr.ref(),
+ compu_method_ref=boolean_compu_method.ref())
+ boolean_impl_type = ar_element.ImplementationDataType("boolean",
+ category="VALUE",
+ sw_data_def_props=sw_data_def_props)
+ packages["PlatformImplementationDataTypes"].append(boolean_impl_type)
+ sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref())
+ uint8_impl_type = ar_element.ImplementationDataType("uint8",
+ category="VALUE",
+ sw_data_def_props=sw_data_def_props)
+ packages["PlatformImplementationDataTypes"].append(uint8_impl_type)
+ sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint16_base_type.ref())
+ uint16_impl_type = ar_element.ImplementationDataType("uint16",
+ category="VALUE",
+ sw_data_def_props=sw_data_def_props)
+ packages["PlatformImplementationDataTypes"].append(uint16_impl_type)
+ sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint32_base_type.ref())
+ uint32_impl_type = ar_element.ImplementationDataType("uint32",
+ category="VALUE",
+ sw_data_def_props=sw_data_def_props)
+ packages["PlatformImplementationDataTypes"].append(uint32_impl_type)
+
+
+def create_vehicle_speed_interface(packages: dict[str, ar_element.Package]) -> ar_element.SenderReceiverInterface:
+ """
+ Create sender-receiver port interfaces used in example
+ """
+ uint16_impl_t = packages["PlatformImplementationDataTypes"].find("uint16")
+ port_interface = ar_element.SenderReceiverInterface("VehicleSpeed_I")
+ port_interface.create_data_element("VehicleSpeed", type_ref=uint16_impl_t.ref())
+ packages["PortInterfaces"].append(port_interface)
+ return port_interface
+
+
+def create_init_value(packages, name: str, value: Any) -> ar_element.ConstantSpecification:
+ """
+ Creates VehicleSpeed init value
+ """
+ constant = ar_element.ConstantSpecification.make_constant(name, value)
+ packages["Constants"].append(constant)
+ return constant
+
+
+def create_application_swc(packages):
+ """
+ Creates application SW component
+ """
+ swc = ar_element.ApplicationSoftwareComponentType("MyApplication")
+ packages["ComponentTypes"].append(swc)
+ return swc
+
+
+class TestSenderPort(unittest.TestCase):
+
+ def test_init_value_ref(self):
+ workspace = autosar.xml.Workspace()
+ packages = create_packages(workspace)
+ create_platform_types(packages)
+ port_interface = create_vehicle_speed_interface(packages)
+ init_value = create_init_value(packages, "VehicleSpeed_IV", 65535)
+ swc = create_application_swc(packages)
+ port = swc.create_provide_port("VehicleSpeed", port_interface, com_spec={'init_value_ref': init_value.ref()})
+ self.assertIsInstance(port, ar_element.ProvidePortPrototype)
+ com_spec: ar_element.NonqueuedSenderComSpec = port.com_spec[0]
+ self.assertIsInstance(com_spec, ar_element.NonqueuedSenderComSpec)
+ self.assertIsInstance(com_spec.init_value, ar_element.ConstantReference)
+ self.assertEqual(str(com_spec.init_value.constant_ref), "/Constants/VehicleSpeed_IV")
+
+ def test_numerical_init_value(self):
+ workspace = autosar.xml.Workspace()
+ packages = create_packages(workspace)
+ create_platform_types(packages)
+ port_interface = create_vehicle_speed_interface(packages)
+ swc = create_application_swc(packages)
+ port = swc.create_provide_port("VehicleSpeed", port_interface, com_spec={'init_value': 65535})
+ self.assertIsInstance(port, ar_element.ProvidePortPrototype)
+ com_spec: ar_element.NonqueuedSenderComSpec = port.com_spec[0]
+ self.assertIsInstance(com_spec, ar_element.NonqueuedSenderComSpec)
+ self.assertIsInstance(com_spec.init_value, ar_element.NumericalValueSpecification)
+ self.assertEqual(com_spec.init_value.value, 65535)
+
+
+class TestReceiverPort(unittest.TestCase):
+
+ def test_init_value_ref(self):
+ workspace = autosar.xml.Workspace()
+ packages = create_packages(workspace)
+ create_platform_types(packages)
+ port_interface = create_vehicle_speed_interface(packages)
+ init_value = create_init_value(packages, "VehicleSpeed_IV", 65535)
+ swc = create_application_swc(packages)
+ port = swc.create_require_port("VehicleSpeed", port_interface, com_spec={'init_value_ref': init_value.ref()})
+ self.assertIsInstance(port, ar_element.RequirePortPrototype)
+ com_spec: ar_element.NonqueuedReceiverComSpec = port.com_spec[0]
+ self.assertIsInstance(com_spec, ar_element.NonqueuedReceiverComSpec)
+ self.assertIsInstance(com_spec.init_value, ar_element.ConstantReference)
+ self.assertEqual(str(com_spec.init_value.constant_ref), "/Constants/VehicleSpeed_IV")
+
+ def test_numerical_init_value(self):
+ workspace = autosar.xml.Workspace()
+ packages = create_packages(workspace)
+ create_platform_types(packages)
+ port_interface = create_vehicle_speed_interface(packages)
+ swc = create_application_swc(packages)
+ port = swc.create_require_port("VehicleSpeed", port_interface, com_spec={'init_value': 65535})
+ self.assertIsInstance(port, ar_element.RequirePortPrototype)
+ com_spec: ar_element.NonqueuedReceiverComSpec = port.com_spec[0]
+ self.assertIsInstance(com_spec, ar_element.NonqueuedReceiverComSpec)
+ self.assertIsInstance(com_spec.init_value, ar_element.NumericalValueSpecification)
+ self.assertEqual(com_spec.init_value.value, 65535)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/xml/test_software_component.py b/tests/xml/test_software_component_elements.py
similarity index 99%
rename from tests/xml/test_software_component.py
rename to tests/xml/test_software_component_elements.py
index 01ee576..39d5cf1 100644
--- a/tests/xml/test_software_component.py
+++ b/tests/xml/test_software_component_elements.py
@@ -1,4 +1,4 @@
-"""Unit tests for software components"""
+"""Unit tests for reading/writing software component elements"""
# pylint: disable=missing-class-docstring, missing-function-docstring
import os