From 01cdafe56ce39bc0ec504a2c1bfc37d0392afa78 Mon Sep 17 00:00:00 2001 From: Daniel Thaler Date: Tue, 29 Aug 2023 21:50:45 +0200 Subject: [PATCH] improve API ergonomics --- autosar_data.pyi | 9 +- src/arxmlfile.rs | 29 ++++-- src/element.rs | 34 +++---- src/lib.rs | 157 ++++++++++++++--------------- src/model.rs | 17 ++-- src/version.rs | 35 +++++++ test/arxmlfile_test.py | 40 ++++++-- test/element_test.py | 219 +++++++++++++++++++++++++++++++++++------ test/model_test.py | 91 ++++++++++++++--- test/test.py | 13 ++- test/version_test.py | 47 +++++---- 11 files changed, 493 insertions(+), 198 deletions(-) diff --git a/autosar_data.pyi b/autosar_data.pyi index cf7089a..e80771f 100644 --- a/autosar_data.pyi +++ b/autosar_data.pyi @@ -87,13 +87,13 @@ class AutosarModel: """ def __repr__(self) -> str: ... def __str__(self) -> str: ... - def create_file(self, filename: str, version: AutosarVersion) -> ArxmlFile: + def create_file(self, filename: str, version: AutosarVersion = AutosarVersion.LATEST) -> ArxmlFile: """create a new file in the model""" ... - def load_buffer(self, buffer: str, filename: str, strict: bool) -> Tuple[ArxmlFile, List[str]]: + def load_buffer(self, buffer: str, filename: str, strict: bool = False) -> Tuple[ArxmlFile, List[str]]: """load a buffer (string) as arxml""" ... - def load_file(self, filename: str, strict: bool) -> Tuple[ArxmlFile, List[str]]: + def load_file(self, filename: str, strict: bool = False) -> Tuple[ArxmlFile, List[str]]: """load a file as arxml""" ... def remove_file(self, arxmlfile: ArxmlFile) -> None: @@ -253,9 +253,6 @@ class Element: def set_attribute(self, attrname: AttributeName, chardata: CharacterData) -> None: """set the given attribute to the provided value. If the attribute is valid for this element it will be created or modified as needed.""" ... - def set_attribute_string(self, attrname: AttributeName, value: str) -> None: - """like set_attribute, but the input will be converted to the target data type as needed""" - ... def remove_attribute(self, attrname: AttributeName) -> None: """remove an attribute from the element""" ... diff --git a/src/arxmlfile.rs b/src/arxmlfile.rs index c2c6daa..57d0fa5 100644 --- a/src/arxmlfile.rs +++ b/src/arxmlfile.rs @@ -17,14 +17,14 @@ impl ArxmlFile { self.serialize() } - fn __richcmp__(&self, other: &ArxmlFile, op: pyo3::basic::CompareOp) -> bool { + fn __richcmp__(&self, other: &ArxmlFile, op: pyo3::basic::CompareOp) -> PyResult { match op { - pyo3::pyclass::CompareOp::Eq => self.0 == other.0, - pyo3::pyclass::CompareOp::Ne => self.0 != other.0, - pyo3::pyclass::CompareOp::Lt - | pyo3::pyclass::CompareOp::Le - | pyo3::pyclass::CompareOp::Gt - | pyo3::pyclass::CompareOp::Ge => false, + pyo3::pyclass::CompareOp::Eq => Ok(self.0 == other.0), + pyo3::pyclass::CompareOp::Ne => Ok(self.0 != other.0), + pyo3::pyclass::CompareOp::Lt => Err(pyo3::exceptions::PyTypeError::new_err("'<' is not supported between instances of 'builtins.Element' and 'builtins.Element'")), + pyo3::pyclass::CompareOp::Le => Err(pyo3::exceptions::PyTypeError::new_err("'<=' is not supported between instances of 'builtins.Element' and 'builtins.Element'")), + pyo3::pyclass::CompareOp::Gt => Err(pyo3::exceptions::PyTypeError::new_err("'>' is not supported between instances of 'builtins.Element' and 'builtins.Element'")), + pyo3::pyclass::CompareOp::Ge => Err(pyo3::exceptions::PyTypeError::new_err("'>=' is not supported between instances of 'builtins.Element' and 'builtins.Element'")), } } @@ -75,7 +75,10 @@ impl ArxmlFile { IncompatibleAttributeError { element: Element(element.to_owned()), attribute: attribute.to_string(), - allowed_versions: expand_version_mask(*version_mask).iter().map(|&v| v.into()).collect(), + allowed_versions: expand_version_mask(*version_mask) + .iter() + .map(|&v| v.into()) + .collect(), target_version, }, ) @@ -92,7 +95,10 @@ impl ArxmlFile { element: Element(element.to_owned()), attribute: attribute.to_string(), attribute_value: attribute_value.to_owned(), - allowed_versions: expand_version_mask(*version_mask).iter().map(|&v| v.into()).collect(), + allowed_versions: expand_version_mask(*version_mask) + .iter() + .map(|&v| v.into()) + .collect(), target_version, }, ) @@ -105,7 +111,10 @@ impl ArxmlFile { py, IncompatibleElementError { element: Element(element.to_owned()), - allowed_versions: expand_version_mask(*version_mask).iter().map(|&v| v.into()).collect(), + allowed_versions: expand_version_mask(*version_mask) + .iter() + .map(|&v| v.into()) + .collect(), target_version, }, ) diff --git a/src/element.rs b/src/element.rs index 9585ba2..a12ae5f 100644 --- a/src/element.rs +++ b/src/element.rs @@ -15,14 +15,14 @@ impl Element { self.0.serialize() } - fn __richcmp__(&self, other: &Element, op: pyo3::basic::CompareOp) -> bool { + fn __richcmp__(&self, other: &Element, op: pyo3::basic::CompareOp) -> PyResult { match op { - pyo3::pyclass::CompareOp::Eq => self.0 == other.0, - pyo3::pyclass::CompareOp::Ne => self.0 != other.0, - pyo3::pyclass::CompareOp::Lt - | pyo3::pyclass::CompareOp::Le - | pyo3::pyclass::CompareOp::Gt - | pyo3::pyclass::CompareOp::Ge => false, + pyo3::pyclass::CompareOp::Eq => Ok(self.0 == other.0), + pyo3::pyclass::CompareOp::Ne => Ok(self.0 != other.0), + pyo3::pyclass::CompareOp::Lt => Err(pyo3::exceptions::PyTypeError::new_err("'<' is not supported between instances of 'builtins.Element' and 'builtins.Element'")), + pyo3::pyclass::CompareOp::Le => Err(pyo3::exceptions::PyTypeError::new_err("'<=' is not supported between instances of 'builtins.Element' and 'builtins.Element'")), + pyo3::pyclass::CompareOp::Gt => Err(pyo3::exceptions::PyTypeError::new_err("'>' is not supported between instances of 'builtins.Element' and 'builtins.Element'")), + pyo3::pyclass::CompareOp::Ge => Err(pyo3::exceptions::PyTypeError::new_err("'>=' is not supported between instances of 'builtins.Element' and 'builtins.Element'")), } } @@ -251,10 +251,9 @@ impl Element { } fn remove_character_content_item(&self, position: usize) -> PyResult<()> { - match self.0.remove_character_content_item(position) { - Ok(()) => Ok(()), - Err(error) => Err(AutosarDataError::new_err(error.to_string())), - } + self.0 + .remove_character_content_item(position) + .map_err(|error| AutosarDataError::new_err(error.to_string())) } #[getter] @@ -272,7 +271,7 @@ impl Element { AttributeIterator(self.0.attributes()) } - fn attribute_value(&self, attrname_str: String) -> PyResult> { + pub(crate) fn attribute_value(&self, attrname_str: String) -> PyResult> { let attrname = get_attribute_name(attrname_str)?; Ok(self .0 @@ -280,11 +279,11 @@ impl Element { .map(|cdata| character_data_to_object(&cdata))) } - fn set_attribute(&self, attrname_str: String, value: PyObject) -> PyResult<()> { + pub(crate) fn set_attribute(&self, attrname_str: String, value: PyObject) -> PyResult<()> { let attrname = get_attribute_name(attrname_str)?; let attrspec = self.0.element_type().find_attribute_spec(attrname).ok_or( AutosarDataError::new_err( - autosar_data_rs::AutosarDataError::IncorrectContentType.to_string(), + autosar_data_rs::AutosarDataError::InvalidAttribute.to_string(), ), )?; let cdata = extract_character_data(attrspec.spec, value)?; @@ -293,13 +292,6 @@ impl Element { .map_err(|error| AutosarDataError::new_err(error.to_string())) } - fn set_attribute_string(&self, attrname_str: String, text: &str) -> PyResult<()> { - let attrname = get_attribute_name(attrname_str)?; - self.0 - .set_attribute_string(attrname, text) - .map_err(|error| AutosarDataError::new_err(error.to_string())) - } - fn remove_attribute(&self, attrname_str: String) -> PyResult { let attrname = get_attribute_name(attrname_str)?; Ok(self.0.remove_attribute(attrname)) diff --git a/src/lib.rs b/src/lib.rs index cb80105..8afe95d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use ::autosar_data as autosar_data_rs; +use autosar_data_rs::CharacterData; use autosar_data_specification::expand_version_mask; use autosar_data_specification::CharacterDataSpec; use pyo3::create_exception; @@ -91,7 +92,9 @@ struct ElementType(autosar_data_specification::ElementType); #[pyclass(frozen)] /// An attribute on an element struct Attribute { + #[pyo3(get)] pub attrname: String, + #[pyo3(get)] pub content: PyObject, } @@ -355,16 +358,6 @@ impl Attribute { fn __str__(&self) -> String { format!("Attribute({}=\"{}\")", self.attrname, self.content) } - - #[getter] - fn attrname(&self) -> String { - self.attrname.to_string() - } - - #[getter] - fn content(&self) -> &PyObject { - &self.content - } } #[pymethods] @@ -376,18 +369,18 @@ impl ValidSubElementInfo { /// Provides functionality to read, modify and write Autosar arxml files, /// both separately and in projects consisting of multiple files. -/// +/// /// Classes: -/// +/// /// - ArxmlFile /// - AutosarModel /// - AutosarVersion /// - Element /// - ElementType /// - ValidSubElementInfo -/// +/// /// Variables: -/// +/// /// - __version__ #[pymodule] fn autosar_data(py: Python, m: &PyModule) -> PyResult<()> { @@ -414,73 +407,81 @@ fn autosar_data(py: Python, m: &PyModule) -> PyResult<()> { fn extract_character_data( spec: &CharacterDataSpec, - any: PyObject, + object: PyObject, ) -> PyResult { Python::with_gil(|py| { - if let Ok(text) = any.extract::(py) { - parse_cdata_string(spec, text).map_err(|_| { - AutosarDataError::new_err( - autosar_data_rs::AutosarDataError::IncorrectContentType.to_string(), - ) - }) - } else if let Ok(val) = any.extract::(py) { - Ok(autosar_data_rs::CharacterData::UnsignedInteger(val)) - } else if let Ok(val) = any.extract::(py) { - Ok(autosar_data_rs::CharacterData::Double(val)) - } else { - Err(AutosarDataError::new_err( - autosar_data_rs::AutosarDataError::IncorrectContentType.to_string(), - )) - } - }) -} - -fn parse_cdata_string( - spec: &CharacterDataSpec, - text: String, -) -> Result { - match spec { - CharacterDataSpec::Enum { items } => { - let enumitem = autosar_data_rs::EnumItem::from_str(&text).map_err(|_| ())?; - if items.iter().any(|(spec_item, _)| *spec_item == enumitem) { - Ok(autosar_data_rs::CharacterData::Enum(enumitem)) - } else { - Err(()) + let any: &PyAny = object.as_ref(py); + match spec { + CharacterDataSpec::Enum { .. } => { + if let Ok(strval) = any.extract::() { + if let Ok(enumitem) = autosar_data_rs::EnumItem::from_str(&strval) { + Ok(CharacterData::Enum(enumitem)) + } else { + Err(pyo3::exceptions::PyValueError::new_err(format!( + "string value '{strval}' cannot be converted to 'EnumItem'" + ))) + } + } else { + Err(pyo3::exceptions::PyTypeError::new_err(format!( + "'{}' cannot be converted to 'EnumItem'", + any.get_type() + ))) + } } - } - CharacterDataSpec::Pattern { - check_fn, - max_length, - .. - } => { - if text.len() < max_length.unwrap_or(usize::MAX) && check_fn(text.as_bytes()) { - Ok(autosar_data_rs::CharacterData::String(text)) - } else { - Err(()) + CharacterDataSpec::Pattern { .. } | CharacterDataSpec::String { .. } => { + if let Ok(text) = any.extract::() { + Ok(CharacterData::String(text)) + } else if let Ok(intval) = any.extract::() { + Ok(CharacterData::String(intval.to_string())) + } else if let Ok(floatval) = any.extract::() { + Ok(CharacterData::String(floatval.to_string())) + } else { + Err(pyo3::exceptions::PyTypeError::new_err(format!( + "'{}' cannot be converted to 'str'", + any.get_type() + ))) + } } - } - CharacterDataSpec::String { max_length, .. } => { - if text.len() < max_length.unwrap_or(usize::MAX) { - Ok(autosar_data_rs::CharacterData::String(text)) - } else { - Err(()) + CharacterDataSpec::UnsignedInteger => { + if let Ok(strval) = any.extract::() { + if let Ok(intval) = strval.parse() { + Ok(CharacterData::UnsignedInteger(intval)) + } else { + Err(pyo3::exceptions::PyValueError::new_err(format!( + "invalid literal '{strval}' for conversion to int" + ))) + } + } else if let Ok(intval) = any.extract::() { + Ok(CharacterData::UnsignedInteger(intval)) + } else { + Err(pyo3::exceptions::PyTypeError::new_err(format!( + "'{}' cannot be converted to 'int'", + any.get_type() + ))) + } } - } - CharacterDataSpec::UnsignedInteger => { - if let Ok(val) = text.parse() { - Ok(autosar_data_rs::CharacterData::UnsignedInteger(val)) - } else { - Err(()) - } - } - CharacterDataSpec::Double => { - if let Ok(val) = text.parse() { - Ok(autosar_data_rs::CharacterData::Double(val)) - } else { - Err(()) + CharacterDataSpec::Double => { + if let Ok(strval) = any.extract::() { + if let Ok(floatval) = strval.parse() { + Ok(CharacterData::Double(floatval)) + } else { + Err(pyo3::exceptions::PyValueError::new_err(format!( + "invalid literal '{strval}' for conversion to float" + ))) + } + } else if let Ok(intval) = any.extract::() { + Ok(CharacterData::Double(intval as f64)) + } else if let Ok(floatval) = any.extract::() { + Ok(CharacterData::Double(floatval)) + } else { + Err(pyo3::exceptions::PyTypeError::new_err(format!( + "'{}' cannot be converted to 'float'", + any.get_type() + ))) + } } } - } + }) } fn character_data_to_object(cdata: &autosar_data_rs::CharacterData) -> PyObject { @@ -525,9 +526,11 @@ fn version_mask_from_any(version_obj: PyObject) -> PyResult { println!("mask from single version: {:x}", ver as u32); Ok(ver as u32) } else { - Err(AutosarDataError::new_err( - autosar_data_rs::AutosarDataError::IncorrectContentType.to_string(), - )) + let any = version_obj.as_ref(py); + Err(pyo3::exceptions::PyTypeError::new_err(format!( + "'{}' cannot be converted to 'VersionSpecification'", + any.get_type() + ))) } }) } diff --git a/src/model.rs b/src/model.rs index f503466..f979768 100644 --- a/src/model.rs +++ b/src/model.rs @@ -21,14 +21,14 @@ impl AutosarModel { self.0.root_element().serialize() } - fn __richcmp__(&self, other: &AutosarModel, op: pyo3::basic::CompareOp) -> bool { + fn __richcmp__(&self, other: &AutosarModel, op: pyo3::basic::CompareOp) -> PyResult { match op { - pyo3::pyclass::CompareOp::Eq => self.0 == other.0, - pyo3::pyclass::CompareOp::Ne => self.0 != other.0, - pyo3::pyclass::CompareOp::Lt - | pyo3::pyclass::CompareOp::Le - | pyo3::pyclass::CompareOp::Gt - | pyo3::pyclass::CompareOp::Ge => false, + pyo3::pyclass::CompareOp::Eq => Ok(self.0 == other.0), + pyo3::pyclass::CompareOp::Ne => Ok(self.0 != other.0), + pyo3::pyclass::CompareOp::Lt => Err(pyo3::exceptions::PyTypeError::new_err("'<' is not supported between instances of 'builtins.AutosarModel' and 'builtins.AutosarModel'")), + pyo3::pyclass::CompareOp::Le => Err(pyo3::exceptions::PyTypeError::new_err("'<=' is not supported between instances of 'builtins.AutosarModel' and 'builtins.AutosarModel'")), + pyo3::pyclass::CompareOp::Gt => Err(pyo3::exceptions::PyTypeError::new_err("'>' is not supported between instances of 'builtins.AutosarModel' and 'builtins.AutosarModel'")), + pyo3::pyclass::CompareOp::Ge => Err(pyo3::exceptions::PyTypeError::new_err("'>=' is not supported between instances of 'builtins.AutosarModel' and 'builtins.AutosarModel'")), } } @@ -39,6 +39,7 @@ impl AutosarModel { } /// create a new file in the model + #[pyo3(signature = (filename, version=AutosarVersion::Latest))] fn create_file(&self, filename: &str, version: AutosarVersion) -> PyResult { match self.0.create_file(filename, version.into()) { Ok(file) => Ok(ArxmlFile(file)), @@ -47,6 +48,7 @@ impl AutosarModel { } /// load a buffer (string) as arxml + #[pyo3(signature = (buffer, filename, strict=false))] fn load_buffer( &self, buffer: &str, @@ -63,6 +65,7 @@ impl AutosarModel { } /// load a file as arxml + #[pyo3(signature = (filename, strict=false))] fn load_file(&self, filename: &str, strict: bool) -> PyResult<(ArxmlFile, Vec)> { match self.0.load_file(filename, strict) { Ok((file, warn)) => { diff --git a/src/version.rs b/src/version.rs index 100a1f4..d425d9e 100644 --- a/src/version.rs +++ b/src/version.rs @@ -5,25 +5,46 @@ use std::str::FromStr; #[pyclass(frozen)] #[derive(Debug, Clone, Copy)] pub(crate) enum AutosarVersion { + #[pyo3(name = "AUTOSAR_4_0_1")] Autosar_4_0_1, + #[pyo3(name = "AUTOSAR_4_0_2")] Autosar_4_0_2, + #[pyo3(name = "AUTOSAR_4_0_3")] Autosar_4_0_3, + #[pyo3(name = "AUTOSAR_4_1_1")] Autosar_4_1_1, + #[pyo3(name = "AUTOSAR_4_1_2")] Autosar_4_1_2, + #[pyo3(name = "AUTOSAR_4_1_3")] Autosar_4_1_3, + #[pyo3(name = "AUTOSAR_4_2_1")] Autosar_4_2_1, + #[pyo3(name = "AUTOSAR_4_2_2")] Autosar_4_2_2, + #[pyo3(name = "AUTOSAR_4_3_0")] Autosar_4_3_0, + #[pyo3(name = "AUTOSAR_00042")] Autosar_00042, + #[pyo3(name = "AUTOSAR_00043")] Autosar_00043, + #[pyo3(name = "AUTOSAR_00044")] Autosar_00044, + #[pyo3(name = "AUTOSAR_00045")] Autosar_00045, + #[pyo3(name = "AUTOSAR_00046")] Autosar_00046, + #[pyo3(name = "AUTOSAR_00047")] Autosar_00047, + #[pyo3(name = "AUTOSAR_00048")] Autosar_00048, + #[pyo3(name = "AUTOSAR_00049")] Autosar_00049, + #[pyo3(name = "AUTOSAR_00050")] Autosar_00050, + #[pyo3(name = "AUTOSAR_00051")] Autosar_00051, + #[pyo3(name = "LATEST")] + Latest, } #[pymethods] @@ -43,6 +64,19 @@ impl AutosarVersion { let ver: autosar_data_specification::AutosarVersion = (*self).into(); ver.to_string() } + + fn __richcmp__(&self, other: AutosarVersion, op: pyo3::basic::CompareOp) -> bool { + let ver1: autosar_data_specification::AutosarVersion = (*self).into(); + let ver2: autosar_data_specification::AutosarVersion = other.into(); + match op { + pyo3::pyclass::CompareOp::Eq => ver1 == ver2, + pyo3::pyclass::CompareOp::Ne => ver1 != ver2, + pyo3::pyclass::CompareOp::Lt => (ver1 as u32) < (ver2 as u32), + pyo3::pyclass::CompareOp::Le => (ver1 as u32) <= (ver2 as u32), + pyo3::pyclass::CompareOp::Gt => (ver1 as u32) > (ver2 as u32), + pyo3::pyclass::CompareOp::Ge => (ver1 as u32) >= (ver2 as u32), + } + } } impl From for autosar_data_specification::AutosarVersion { @@ -67,6 +101,7 @@ impl From for autosar_data_specification::AutosarVersion { AutosarVersion::Autosar_00049 => Self::Autosar_00049, AutosarVersion::Autosar_00050 => Self::Autosar_00050, AutosarVersion::Autosar_00051 => Self::Autosar_00051, + AutosarVersion::Latest => Self::LATEST, } } } diff --git a/test/arxmlfile_test.py b/test/arxmlfile_test.py index d64727c..413deec 100644 --- a/test/arxmlfile_test.py +++ b/test/arxmlfile_test.py @@ -4,8 +4,8 @@ def test_arxlfile_basic() -> None: model = AutosarModel() - file1 = model.create_file("filename1.arxml", AutosarVersion.Autosar_00051) - file2 = model.create_file("filename2.arxml", AutosarVersion.Autosar_00051) + file1 = model.create_file("filename1.arxml", AutosarVersion.AUTOSAR_00051) + file2 = model.create_file("filename2.arxml", AutosarVersion.AUTOSAR_00051) assert isinstance(file1, ArxmlFile) assert isinstance(file2, ArxmlFile) @@ -27,9 +27,9 @@ def test_arxlfile_basic() -> None: file1.filename = file2.filename # each file has a version - assert file1.version == AutosarVersion.Autosar_00051 - file1.version = AutosarVersion.Autosar_4_3_0 - assert file1.version == AutosarVersion.Autosar_4_3_0 + assert file1.version == AutosarVersion.AUTOSAR_00051 + file1.version = AutosarVersion.AUTOSAR_4_3_0 + assert file1.version == AutosarVersion.AUTOSAR_4_3_0 # ArxmlFile has __str__ and __repr__ arxmlfile_repr = file1.__repr__() @@ -54,12 +54,15 @@ def test_arxlfile_basic() -> None: model = None with pytest.raises(AutosarDataError): print(file1.model) + # other operations also require a valid model + with pytest.raises(AutosarDataError): + print(file1.serialize()) def test_check_version_compatibility() -> None: model = AutosarModel() - file1 = model.create_file("filename", AutosarVersion.Autosar_00050) + file1 = model.create_file("filename", AutosarVersion.AUTOSAR_00050) el_elements = model.root_element \ .create_sub_element("AR-PACKAGES") \ .create_named_sub_element("AR-PACKAGE", "Pkg") \ @@ -73,8 +76,11 @@ def test_check_version_compatibility() -> None: el_blueprint_ref.set_attribute("DEST", "ABSTRACT-IMPLEMENTATION-DATA-TYPE") el_adaptive_sw_component_type = el_elements \ .create_named_sub_element("ADAPTIVE-APPLICATION-SW-COMPONENT-TYPE", "AdaptiveApplicationSwComponentType") + + with pytest.raises(AutosarDataError): + file1.version = AutosarVersion.AUTOSAR_4_3_0 # fails because there are compatibility problems - compat_problems = file1.check_version_compatibility(AutosarVersion.Autosar_4_3_0) + compat_problems = file1.check_version_compatibility(AutosarVersion.AUTOSAR_4_3_0) assert len(compat_problems) == 3 assert isinstance(compat_problems[0], IncompatibleAttributeError) assert isinstance(compat_problems[1], IncompatibleAttributeValueError) @@ -91,7 +97,7 @@ def test_check_version_compatibility() -> None: # IncompatibleAttributeValueError assert compat_problems[1].element == el_blueprint_ref assert compat_problems[1].attribute == "DEST" - assert compat_problems[1].attribute_value == "ABSTRACT-IMPLEMENTATION-DATA-TYPE" # todo - type conversion of AttributeValue to string? + assert compat_problems[1].attribute_value == "ABSTRACT-IMPLEMENTATION-DATA-TYPE" error_str = compat_problems[1].__str__() error_repr = compat_problems[1].__repr__() assert not error_str is None @@ -102,4 +108,20 @@ def test_check_version_compatibility() -> None: error_str = compat_problems[2].__str__() error_repr = compat_problems[2].__repr__() assert not error_str is None - assert not error_repr is None \ No newline at end of file + assert not error_repr is None + + +def test_file_misc() -> None: + model = AutosarModel() + + file1 = model.create_file("filename1.arxml", AutosarVersion.AUTOSAR_00051) + file2 = model.create_file("filename2.arxml", AutosarVersion.AUTOSAR_00051) + + with pytest.raises(TypeError): + file1 < file2 + with pytest.raises(TypeError): + file1 > file2 + with pytest.raises(TypeError): + file1 <= file2 + with pytest.raises(TypeError): + file1 >= file2 diff --git a/test/element_test.py b/test/element_test.py index 8a5776e..b347609 100644 --- a/test/element_test.py +++ b/test/element_test.py @@ -1,10 +1,9 @@ from autosar_data import * import pytest -def test_element_basic() -> None: +def test_element_basic_1() -> None: model = AutosarModel() - - # create some elements + arxmlfile = model.create_file("file") el_ar_packages = model.root_element.create_sub_element("AR-PACKAGES") el_ar_package = el_ar_packages.create_named_sub_element("AR-PACKAGE", "Pkg1") assert isinstance(el_ar_packages, Element) @@ -23,6 +22,9 @@ def test_element_basic() -> None: el_short_name = el_ar_package.get_sub_element("SHORT-NAME") assert isinstance(el_short_name, Element) + with pytest.raises(AutosarDataError): + el_ar_package.get_sub_element("not an element") + # properties of named elements assert el_ar_package.item_name == "Pkg1" assert el_ar_package.path == "/Pkg1" @@ -32,57 +34,81 @@ def test_element_basic() -> None: assert el_ar_package.item_name == "NewName" assert el_ar_package.path == "/NewName" + # not every string is a valid name, for example the name cannot contain spaces or start with a digit + with pytest.raises(AutosarDataError): + el_ar_package.item_name = "text text" + # these properies are not valid for elements that are not identifiable assert el_ar_packages.is_identifiable == False assert el_ar_packages.item_name is None with pytest.raises(AutosarDataError): print(el_ar_packages.path) + + # a removed element still exists until there are no more references to it, but it can no longer be used + el_ar_packages.remove_sub_element(el_ar_package) + with pytest.raises(AutosarDataError): + el_ar_package.parent + with pytest.raises(AutosarDataError): + el_ar_package.path + with pytest.raises(AutosarDataError): + el_ar_package.add_to_file(arxmlfile) + with pytest.raises(AutosarDataError): + el_ar_package.file_membership + +def test_element_basic_2() -> None: + model = AutosarModel() + el_ar_package = model.root_element.create_sub_element("AR-PACKAGES").create_named_sub_element("AR-PACKAGE", "Pkg1") + el_root = model.root_element # the behavior of the element is determined by its element_type - assert el_ar_packages.is_identifiable == el_ar_packages.element_type.is_named - assert el_ar_packages.is_reference == el_ar_packages.element_type.is_ref - assert not el_ar_packages.element_type.is_ordered - assert el_ar_packages.element_type.splittable != 0 + assert el_root.is_identifiable == el_root.element_type.is_named + assert el_root.is_reference == el_root.element_type.is_ref + assert not el_root.element_type.is_ordered + assert el_root.element_type.splittable != 0 # Element has __str__ and __repr__ - el_ar_packages_repr = el_ar_packages.__repr__() + el_ar_packages_repr = el_root.__repr__() assert not el_ar_packages_repr is None - el_ar_packages_str = el_ar_packages.__str__() + el_ar_packages_str = el_root.__str__() assert not el_ar_packages_str is None assert el_ar_packages_repr != el_ar_packages_str # elements can be serialized - el_ar_packages_text = el_ar_packages.serialize() + el_ar_packages_text = el_root.serialize() # this is currently the same as __str__() assert el_ar_packages_text == el_ar_packages_str # Element has __hash__ - elementset = set([el_ar_packages, el_ar_package]) + elementset = set([el_root, el_ar_package]) assert len(elementset) == 2 + +def test_element_basic_3() -> None: + model = AutosarModel() + el_ar_packages = model.root_element.create_sub_element("AR-PACKAGES") + el_ar_package = el_ar_packages.create_named_sub_element("AR-PACKAGE", "Pkg1") + # Element comparison - assert model.get_element_by_path("/NewName") == el_ar_package + assert model.get_element_by_path("/Pkg1") == el_ar_package assert el_ar_packages != el_ar_package # Elements can be sorted el_ar_packages.create_named_sub_element("AR-PACKAGE", "AAA") sub_elements = [e for e in el_ar_packages.sub_elements] - assert sub_elements[0].item_name == "NewName" + assert sub_elements[0].item_name == "Pkg1" assert sub_elements[1].item_name == "AAA" # sort all sub elements recursively el_ar_packages.sort() sub_elements = [e for e in el_ar_packages.sub_elements] assert sub_elements[0].item_name == "AAA" - assert sub_elements[1].item_name == "NewName" + assert sub_elements[1].item_name == "Pkg1" # every alement has an "xml path" this path includes the names and item names of all parent elements - assert el_ar_package.xml_path == "///NewName" + assert el_ar_package.xml_path == "///Pkg1" def test_element_content() -> None: model = AutosarModel() - - # create some elements for the test el_ar_packages = model.root_element.create_sub_element("AR-PACKAGES") el_pkg1 = el_ar_packages.create_named_sub_element("AR-PACKAGE", "Pkg1") el_short_name = el_pkg1.get_sub_element("SHORT-NAME") @@ -116,6 +142,10 @@ def test_element_content() -> None: with pytest.raises(AutosarDataError): el_short_name.insert_character_content_item("text", 0) + +def test_element_references() -> None: + model = AutosarModel() + el_ar_packages = model.root_element.create_sub_element("AR-PACKAGES") el_elements = el_ar_packages \ .create_named_sub_element("AR-PACKAGE", "SysPkg") \ .create_sub_element("ELEMENTS") @@ -136,13 +166,13 @@ def test_element_content() -> None: el_fibex_element_ref.character_data = 1 with pytest.raises(AutosarDataError): el_fibex_element_ref.character_data = "? what ?" - with pytest.raises(AutosarDataError): - el_fibex_element_ref.character_data = AutosarVersion.Autosar_00042 # wrong datatype + with pytest.raises(TypeError): + el_fibex_element_ref.character_data = AutosarVersion.AUTOSAR_00042 # wrong datatype # "looks like" an autosar path el_fibex_element_ref.character_data = "/something/else" # the DEST attribute of el_fibex_element_ref takes an enum value, all other values cause an error - with pytest.raises(AutosarDataError): + with pytest.raises(ValueError): el_fibex_element_ref.set_attribute("DEST", "bla") with pytest.raises(AutosarDataError): el_fibex_element_ref.set_attribute("DEST", "default") @@ -159,10 +189,16 @@ def test_element_content() -> None: el_fibex_element_ref.reference_target = el_can_cluster assert el_fibex_element_ref.character_data == "/CanPkg/CanCluster" + # AR-PACKAGES is not a reference element, so setting a reference target isn't possible + with pytest.raises(AutosarDataError): + el_ar_packages.reference_target = el_can_cluster + # remove the character data el_fibex_element_ref.remove_character_data() assert el_fibex_element_ref.character_data is None + +def test_element_character_data_1() -> None: # some elements have the data type double / f64 for their character content model = AutosarModel() el_macrotick = model.root_element \ @@ -174,13 +210,18 @@ def test_element_content() -> None: .create_sub_element("FLEXRAY-CLUSTER-CONDITIONAL") \ .create_sub_element("MACROTICK-DURATION") el_macrotick.character_data = 2.71828 + el_macrotick.character_data = 3 # automatic conversion to double el_macrotick.character_data = "3.1415" # automatic conversion to double - with pytest.raises(AutosarDataError): + assert el_macrotick.character_data == 3.1415 + with pytest.raises(TypeError): + el_macrotick.character_data = model + with pytest.raises(ValueError): el_macrotick.character_data = "not numeric" + +def test_element_character_data_2() -> None: # it seems there is only one element with datatype unsigned integer, and only in Autosar 4.0.1 model = AutosarModel() - arxmlfile = model.create_file("file", AutosarVersion.Autosar_4_0_1) el_cse_code = model.root_element \ .create_sub_element("AR-PACKAGES") \ .create_named_sub_element("AR-PACKAGE", "pkg") \ @@ -191,9 +232,60 @@ def test_element_content() -> None: .create_sub_element("TOLERANCE") \ .create_sub_element("CSE-CODE") el_cse_code.character_data = 42 - el_cse_code.character_data = "42" # automatic conversion - with pytest.raises(AutosarDataError): + el_cse_code.character_data = "123" # automatic conversion + assert el_cse_code.character_data == 123 + with pytest.raises(TypeError): + el_cse_code.character_data = model + with pytest.raises(ValueError): el_cse_code.character_data = "text" + with pytest.raises(TypeError): + el_cse_code.character_data = 3.1 # no automatic conversion from float, truncation should be explicit + + +def test_element_character_data_3() -> None: + model = AutosarModel() + el_fibex_element_ref = model.root_element.create_sub_element("AR-PACKAGES") \ + .create_named_sub_element("AR-PACKAGE", "Pkg") \ + .create_sub_element("ELEMENTS") \ + .create_named_sub_element("SYSTEM", "System") \ + .create_sub_element("FIBEX-ELEMENTS") \ + .create_sub_element("FIBEX-ELEMENT-REF-CONDITIONAL") \ + .create_sub_element("FIBEX-ELEMENT-REF") + el_fibex_element_ref.set_attribute("DEST", "I-SIGNAL") + assert el_fibex_element_ref.attribute_value("DEST") == "I-SIGNAL" + with pytest.raises(ValueError): + el_fibex_element_ref.set_attribute("DEST", "not an enum item") + with pytest.raises(TypeError): + el_fibex_element_ref.set_attribute("DEST", 42) + with pytest.raises(TypeError): + el_fibex_element_ref.set_attribute("DEST", model) + + +def test_element_character_data_4() -> None: + model = AutosarModel() + model.root_element.set_attribute("S", "text") + model.root_element.set_attribute("S", 42) + model.root_element.set_attribute("S", 3.1415) + assert model.root_element.attribute_value("S") == "3.1415" + with pytest.raises(TypeError): + model.root_element.set_attribute("S", model) + + +def test_character_data_5() -> None: + model = AutosarModel() + el_ar_packages = model.root_element.create_sub_element("AR-PACKAGES") + # can't set character data on elements that have ContentType: Elements + with pytest.raises(AutosarDataError): + el_ar_packages.character_data = "abc" + + # can't remove character data from elements that have ContentType: Elements + with pytest.raises(AutosarDataError): + el_ar_packages.remove_character_data() + + # can't remove character data from elements that have ContentType: Elements + with pytest.raises(AutosarDataError): + el_ar_packages.remove_character_content_item(0) + def test_element_creation() -> None: @@ -237,7 +329,7 @@ def test_element_creation() -> None: # not valid: ArPackage inside Arpackage with pytest.raises(AutosarDataError): el_pkg1.move_element_here(el_pkg2) - # valid: ArPackage inside Arpackages + # valid: AR-PACKAGE inside AR-PACKAGES el_pkg1.create_sub_element("AR-PACKAGES").move_element_here(el_pkg2) assert el_pkg2.path == "/Pkg1/Pkg2" assert copied_system.path == "/Pkg1/Pkg2/System" @@ -299,6 +391,49 @@ def test_element_creation() -> None: assert len(element_info) == 13 +def test_element_action_errors() -> None: + model = AutosarModel() + el_ar_packages = model.root_element.create_sub_element("AR-PACKAGES") + el_ar_package = el_ar_packages.create_named_sub_element("AR-PACKAGE", "Pkg") + el_ar_package2 = el_ar_packages.create_named_sub_element("AR-PACKAGE", "Pkg2") + + # cannot create unknown elements, or elements that are not valid sub elements + with pytest.raises(AutosarDataError): + el_ar_package.create_sub_element("not an element") + with pytest.raises(AutosarDataError): + el_ar_package.create_sub_element_at("not an element", 0) + with pytest.raises(AutosarDataError): + el_ar_package.create_sub_element("AUTOSAR") + with pytest.raises(AutosarDataError): + el_ar_package.create_sub_element_at("AUTOSAR", 0) + + with pytest.raises(AutosarDataError): + el_ar_package.create_named_sub_element("not an element", "name") + with pytest.raises(AutosarDataError): + el_ar_package.create_named_sub_element_at("not an element", "name", 0) + with pytest.raises(AutosarDataError): + el_ar_package.create_named_sub_element("AUTOSAR", "name") + with pytest.raises(AutosarDataError): + el_ar_package.create_named_sub_element_at("AUTOSAR", "name", 0) + + # cannot create invalid an structure by copying + with pytest.raises(AutosarDataError): + el_ar_package.create_copied_sub_element(el_ar_package2) + with pytest.raises(AutosarDataError): + el_ar_package.create_copied_sub_element_at(el_ar_package2, 0) + + # cannot create an invalid stucture by moving elements + with pytest.raises(AutosarDataError): + el_ar_package.move_element_here(el_ar_package2) + with pytest.raises(AutosarDataError): + el_ar_package.move_element_here_at(el_ar_package2, 0) + + # can't remove an element that is not a sub element + with pytest.raises(AutosarDataError): + el_ar_package.remove_sub_element(el_ar_package2) + + + def test_element_attributes() -> None: model = AutosarModel() el_autosar = model.root_element @@ -320,10 +455,17 @@ def test_element_attributes() -> None: # attribute values are checked - attribute T must contain a valid timestamp with pytest.raises(AutosarDataError): el_autosar.set_attribute("T", "some text") - # the function set_attribute_string automatically converts an input string to enum or integer if the attribute requires this - el_autosar.set_attribute_string("T", "2023-04-05T12:34:56Z") + # the function set_attribute automatically converts an input string to enum or integer if the attribute requires this + el_autosar.set_attribute("T", "2023-04-05T12:34:56Z") assert el_autosar.attribute_value("T") == "2023-04-05T12:34:56Z" + with pytest.raises(AutosarDataError): + el_autosar.set_attribute("not an attribute", "some text") + with pytest.raises(AutosarDataError): + el_autosar.attribute_value("not an attribute") + with pytest.raises(AutosarDataError): + el_autosar.set_attribute("DEST", 0) + assert len([attr for attr in el_autosar.attributes]) == 5 el_autosar.remove_attribute("T") assert len([attr for attr in el_autosar.attributes]) == 4 @@ -331,8 +473,8 @@ def test_element_attributes() -> None: def test_file_membership() -> None: model = AutosarModel() - file1 = model.create_file("file1", AutosarVersion.Autosar_00050) - file2 = model.create_file("file2", AutosarVersion.Autosar_00050) + file1 = model.create_file("file1", AutosarVersion.AUTOSAR_00050) + file2 = model.create_file("file2", AutosarVersion.AUTOSAR_00050) el_ar_packages = model.root_element.create_sub_element("AR-PACKAGES") el_pkg1 = el_ar_packages.create_named_sub_element("AR-PACKAGE", "Pkg1") el_pkg1.create_sub_element("ELEMENTS") @@ -355,4 +497,21 @@ def test_file_membership() -> None: assert file1_element_count != file2_element_count el_pkg1.add_to_file(file2) - assert file2 in el_pkg1.file_membership[1] \ No newline at end of file + assert file2 in el_pkg1.file_membership[1] + + +def test_element_misc() -> None: + model = AutosarModel() + element = model.root_element + + assert element == element + assert not element != element + + with pytest.raises(TypeError): + element < element + with pytest.raises(TypeError): + element > element + with pytest.raises(TypeError): + element <= element + with pytest.raises(TypeError): + element >= element diff --git a/test/model_test.py b/test/model_test.py index ff43ffb..6943ccc 100644 --- a/test/model_test.py +++ b/test/model_test.py @@ -17,19 +17,19 @@ def test_model_files(tmp_path: str) -> None: # create a file filename1 = os.path.join(tmp_path, "test.arxml") - file1 = model.create_file(filename1, AutosarVersion.Autosar_00051) + file1 = model.create_file(filename1, AutosarVersion.AUTOSAR_00051) assert isinstance(file1, ArxmlFile) assert file1.filename == os.path.join(tmp_path, "test.arxml") # create another file - file2 = model.create_file("test2.arxml", AutosarVersion.Autosar_00051) + file2 = model.create_file("test2.arxml") assert isinstance(file2, ArxmlFile) assert len(model.files) == 2 # create a file with the same name as file1 with pytest.raises(AutosarDataError): # a file called "$tmp_path/test.arxml" already exists in the model - file3 = model.create_file(filename1, AutosarVersion.Autosar_00051) + file3 = model.create_file(filename1) # remove file2 from the model again model.remove_file(file2) @@ -50,7 +50,7 @@ def test_model_files(tmp_path: str) -> None: # can't load a nonexistent file with pytest.raises(AutosarDataError): - model2.load_file("nonexistent_nothing", True) + model2.load_file("nonexistent_nothing") # create a string of arxml data from file1 all_files_text = model.serialize_files() @@ -58,15 +58,58 @@ def test_model_files(tmp_path: str) -> None: # load the string in a new model model3 = AutosarModel() - (m3_file, warnings) = model3.load_buffer(file1_text, "m3_file.arxml", True) + (m3_file, warnings) = model3.load_buffer(file1_text, "m3_file.arxml") assert isinstance(m3_file, ArxmlFile) assert len(warnings) == 0 # can't load nonsense data as arxml with pytest.raises(AutosarDataError): - model3.load_buffer("hello, world!", "m3_file2.arxml", True) + model3.load_buffer("hello, world!", "m3_file2.arxml") + + +def test_strict_parsing(tmp_path: str) -> None: + # the following arxml contains an element from the adaptive platform, but specifies version 4.3.0 + buffer = """ + + + + Pkg + + + AdaptiveApplicationSwComponentType + + + + +""" + model = AutosarModel() + filename = os.path.join(tmp_path, "test.arxml") + # loading the buffer with strict = False succeeds but produces warnings + (arxmlfile, warnings) = model.load_buffer(buffer, filename, False) + assert isinstance(arxmlfile, ArxmlFile) + assert len(warnings) != 0 + # loading with strict = True triggers an exception + with pytest.raises(AutosarDataError): + model.load_buffer(buffer, filename, True) + + model.write() + # erase the model, so that loading the file with the existing filename works + model = AutosarModel() + # loading the file with strict = False succeeds but produces warnings + (arxmlfile, warnings) = model.load_file(filename, False) + assert isinstance(arxmlfile, ArxmlFile) + assert len(warnings) != 0 + # loading with strict = True triggers an exception + with pytest.raises(AutosarDataError): + model.load_file(filename, False) +def test_model_write() -> None: + model = AutosarModel() + model.create_file("/this/path/does/not/exist.arxml") + with pytest.raises(AutosarDataError): + model.write() + def test_model_identifiables() -> None: model = AutosarModel() @@ -117,10 +160,22 @@ def test_model_misc() -> None: # two references to the same model are equal assert model.root_element.model == model # inequalities do not exist - assert not model < model2 - assert not model > model2 - assert not model <= model2 - assert not model >= model2 + with pytest.raises(TypeError): + model < model2 + with pytest.raises(TypeError): + model > model2 + with pytest.raises(TypeError): + model <= model2 + with pytest.raises(TypeError): + model >= model2 + + # models can be hashed + modelset = set([model, model2]) + assert len(modelset) == 2 + + +def test_model_misc_2() -> None: + model = AutosarModel() # the model can be displayed as a string model_str = str.format("{}", model) @@ -130,6 +185,10 @@ def test_model_misc() -> None: model_str = str.format("{}", model.__repr__()) assert not model_str is None + +def test_model_misc_3() -> None: + model = AutosarModel() + # dfs iterator test: create some elements el_elements = model.root_element \ .create_sub_element("AR-PACKAGES") \ @@ -149,6 +208,15 @@ def test_model_misc() -> None: assert elements[4]['depth'] == 3 assert elements[4]['element'].element_name == "ELEMENTS" + +def test_model_misc_4() -> None: + model = AutosarModel() + + # dfs iterator test: create some elements + el_elements = model.root_element \ + .create_sub_element("AR-PACKAGES") \ + .create_named_sub_element("AR-PACKAGE", "Pkg1") \ + .create_sub_element("ELEMENTS") # create a ref element for check_references() el_fibex_element_ref = el_elements \ .create_named_sub_element("SYSTEM", "System") \ @@ -177,7 +245,4 @@ def test_model_misc() -> None: assert subelements[0] == el_pkg1 assert subelements[1] == el_pkg2 - # models can be hashed - modelset = set([model, model2]) - assert len(modelset) == 2 \ No newline at end of file diff --git a/test/test.py b/test/test.py index 70abf12..93fff14 100644 --- a/test/test.py +++ b/test/test.py @@ -11,13 +11,16 @@ def test_others() -> None: assert not ct_repr is None # ElementType - assert model.root_element.element_type.splittable_in(AutosarVersion.Autosar_00042) == False + assert model.root_element.element_type.splittable_in(AutosarVersion.AUTOSAR_00042) == False # find a sub element for a particular version - ar_pkg_type = model.root_element.element_type.find_sub_element("AR-PACKAGES", AutosarVersion.Autosar_4_0_1) - assert ar_pkg_type.splittable_in(AutosarVersion.Autosar_00042) == True + ar_pkg_type = model.root_element.element_type.find_sub_element("AR-PACKAGES", AutosarVersion.AUTOSAR_4_0_1) + assert ar_pkg_type.splittable_in(AutosarVersion.AUTOSAR_00042) == True # find a sub element for multiple versions - ar_pkg_type = model.root_element.element_type.find_sub_element("AR-PACKAGES", [AutosarVersion.Autosar_4_0_1, AutosarVersion.Autosar_4_0_2]) - assert ar_pkg_type.splittable_in(AutosarVersion.Autosar_00042) == True + ar_pkg_type = model.root_element.element_type.find_sub_element("AR-PACKAGES", [AutosarVersion.AUTOSAR_4_0_1, AutosarVersion.AUTOSAR_4_0_2]) + assert ar_pkg_type.splittable_in(AutosarVersion.AUTOSAR_00042) == True + with pytest.raises(TypeError): + model.root_element.element_type.find_sub_element("AR-PACKAGES", "wrong type") + assert AutosarVersion.AUTOSAR_4_0_1 in ar_pkg_type.splittable et_str = ar_pkg_type.__str__() et_repr = ar_pkg_type.__repr__() diff --git a/test/version_test.py b/test/version_test.py index 3ebd3d8..4e86e71 100644 --- a/test/version_test.py +++ b/test/version_test.py @@ -5,101 +5,108 @@ def test_version() -> None: model = AutosarModel() ver = AutosarVersion("AUTOSAR_4-0-1.xsd") - assert ver == AutosarVersion.Autosar_4_0_1 + assert ver == AutosarVersion.AUTOSAR_4_0_1 arxmlfile = model.create_file("AUTOSAR_4-0-1.arxml", ver) assert arxmlfile.version == ver assert ver.__str__() == "AUTOSAR 4.0.1" ver = AutosarVersion("AUTOSAR_4-0-2.xsd") - assert ver == AutosarVersion.Autosar_4_0_2 + assert ver == AutosarVersion.AUTOSAR_4_0_2 arxmlfile = model.create_file("AUTOSAR_4-0-2.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_4-0-3.xsd") - assert ver == AutosarVersion.Autosar_4_0_3 + assert ver == AutosarVersion.AUTOSAR_4_0_3 arxmlfile = model.create_file("AUTOSAR_4-0-3.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_4-1-1.xsd") - assert ver == AutosarVersion.Autosar_4_1_1 + assert ver == AutosarVersion.AUTOSAR_4_1_1 arxmlfile = model.create_file("AUTOSAR_4-1-1.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_4-1-2.xsd") - assert ver == AutosarVersion.Autosar_4_1_2 + assert ver == AutosarVersion.AUTOSAR_4_1_2 arxmlfile = model.create_file("AUTOSAR_4-1-2.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_4-1-3.xsd") - assert ver == AutosarVersion.Autosar_4_1_3 + assert ver == AutosarVersion.AUTOSAR_4_1_3 arxmlfile = model.create_file("AUTOSAR_4-1-3.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_4-2-1.xsd") - assert ver == AutosarVersion.Autosar_4_2_1 + assert ver == AutosarVersion.AUTOSAR_4_2_1 arxmlfile = model.create_file("AUTOSAR_4-2-1.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_4-2-2.xsd") - assert ver == AutosarVersion.Autosar_4_2_2 + assert ver == AutosarVersion.AUTOSAR_4_2_2 arxmlfile = model.create_file("AUTOSAR_4-2-2.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_4-3-0.xsd") - assert ver == AutosarVersion.Autosar_4_3_0 + assert ver == AutosarVersion.AUTOSAR_4_3_0 arxmlfile = model.create_file("AUTOSAR_4-3-0.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00042.xsd") - assert ver == AutosarVersion.Autosar_00042 + assert ver == AutosarVersion.AUTOSAR_00042 arxmlfile = model.create_file("AUTOSAR_00042.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00043.xsd") - assert ver == AutosarVersion.Autosar_00043 + assert ver == AutosarVersion.AUTOSAR_00043 arxmlfile = model.create_file("AUTOSAR_00043.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00044.xsd") - assert ver == AutosarVersion.Autosar_00044 + assert ver == AutosarVersion.AUTOSAR_00044 arxmlfile = model.create_file("AUTOSAR_00044.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00045.xsd") - assert ver == AutosarVersion.Autosar_00045 + assert ver == AutosarVersion.AUTOSAR_00045 arxmlfile = model.create_file("AUTOSAR_00045.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00046.xsd") - assert ver == AutosarVersion.Autosar_00046 + assert ver == AutosarVersion.AUTOSAR_00046 arxmlfile = model.create_file("AUTOSAR_00046.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00047.xsd") - assert ver == AutosarVersion.Autosar_00047 + assert ver == AutosarVersion.AUTOSAR_00047 arxmlfile = model.create_file("AUTOSAR_00047.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00048.xsd") - assert ver == AutosarVersion.Autosar_00048 + assert ver == AutosarVersion.AUTOSAR_00048 arxmlfile = model.create_file("AUTOSAR_00048.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00049.xsd") - assert ver == AutosarVersion.Autosar_00049 + assert ver == AutosarVersion.AUTOSAR_00049 arxmlfile = model.create_file("AUTOSAR_00049.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00050.xsd") - assert ver == AutosarVersion.Autosar_00050 + assert ver == AutosarVersion.AUTOSAR_00050 arxmlfile = model.create_file("AUTOSAR_00050.arxml", ver) assert arxmlfile.version == ver ver = AutosarVersion("AUTOSAR_00051.xsd") - assert ver == AutosarVersion.Autosar_00051 + assert ver == AutosarVersion.AUTOSAR_00051 arxmlfile = model.create_file("AUTOSAR_00051.arxml", ver) assert arxmlfile.version == ver - with pytest.raises(AutosarDataError): ver = AutosarVersion("bad.xsd") + + # test (in)equalities + assert AutosarVersion.AUTOSAR_00051 == AutosarVersion.AUTOSAR_00051 + assert AutosarVersion.AUTOSAR_4_0_1 != AutosarVersion.AUTOSAR_00051 + assert AutosarVersion.AUTOSAR_4_0_1 < AutosarVersion.AUTOSAR_00051 + assert AutosarVersion.AUTOSAR_4_0_1 <= AutosarVersion.AUTOSAR_00051 + assert AutosarVersion.AUTOSAR_00051 > AutosarVersion.AUTOSAR_4_0_1 + assert AutosarVersion.AUTOSAR_00051 >= AutosarVersion.AUTOSAR_4_0_1