From d27552f8255ca850f99df5058e138526e05f4f1c Mon Sep 17 00:00:00 2001 From: James Rosewell Date: Sat, 14 Nov 2026 11:27:02 +0000 Subject: [PATCH 1/2] Test that reading an AspectPropertyValue with no value raises with a message The Null values section of properties.md says reading a value that is not set throws with a message explaining why. With no reason given the value raised Exception(None), whose message is 'None'. --- .../tests/test_aspectproperty_value.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 pipeline/fiftyone_pipeline_core/tests/test_aspectproperty_value.py diff --git a/pipeline/fiftyone_pipeline_core/tests/test_aspectproperty_value.py b/pipeline/fiftyone_pipeline_core/tests/test_aspectproperty_value.py new file mode 100644 index 00000000..a7c36e42 --- /dev/null +++ b/pipeline/fiftyone_pipeline_core/tests/test_aspectproperty_value.py @@ -0,0 +1,62 @@ +# ********************************************************************* +# This Original Work is copyright of 51 Degrees Mobile Experts Limited. +# Copyright 2026 51 Degrees Mobile Experts Limited, Davidson House, +# Forbury Square, Reading, Berkshire, United Kingdom RG1 3EU. +# +# This Original Work is licensed under the European Union Public Licence +# (EUPL) v.1.2 and is subject to its terms as set out below. +# +# If a copy of the EUPL was not distributed with this file, You can obtain +# one at https://opensource.org/licenses/EUPL-1.2. +# +# The 'Compatible Licences' set out in the Appendix to the EUPL (as may be +# amended by the European Commission) shall be deemed incompatible for +# the purposes of the Work and the provisions of the compatibility +# clause in Article 5 of the EUPL shall not apply. +# +# If using the Work as, or as part of, a network application, by +# including the attribution notice(s) required under Article 5 of the EUPL +# in the end user terms of the application under an appropriate heading, +# such notice(s) shall fulfill the requirements of that article. +# ********************************************************************* + +import unittest + +from fiftyone_pipeline_core.aspectproperty_value import AspectPropertyValue + +NO_VALUE = "This instance does not have a set value" + + +class AspectPropertyValueTests(unittest.TestCase): + + """! + Reading the value of an AspectPropertyValue that has no value raises, + with the reason given or, when none was given, a message saying there + is no value, as the Null values section of properties.md in the + specifications asks. A value that is set, whatever it is, is read back + as it was set. + """ + + def test_reading_no_value_raises_with_a_message(self): + cases = [ + ("no reason", AspectPropertyValue(), NO_VALUE), + ("a None reason", AspectPropertyValue(None), NO_VALUE), + ("an empty reason", AspectPropertyValue(""), NO_VALUE), + ("a reason", AspectPropertyValue("No match"), "No match"), + ] + for name, apv, message in cases: + with self.subTest(name): + self.assertFalse(apv.has_value()) + with self.assertRaises(Exception) as raised: + apv.value() + self.assertEqual(message, str(raised.exception)) + + def test_no_reason_leaves_the_message_unset(self): + self.assertIsNone(AspectPropertyValue().no_value_message()) + + def test_a_value_is_read_as_set(self): + for value in ["Value", None, False, 0, "", ["a", "b"]]: + with self.subTest(value=value): + apv = AspectPropertyValue(value=value) + self.assertTrue(apv.has_value()) + self.assertEqual(value, apv.value()) From c7e8e960d42304fa2571dc818234ba319ea58c48 Mon Sep 17 00:00:00 2001 From: James Rosewell Date: Sat, 14 Nov 2026 11:27:03 +0000 Subject: [PATCH 2/2] Raise with a message when reading an AspectPropertyValue with no value and no reason value() raised Exception(None) when no reason was given. It now raises with NO_VALUE_MESSAGE, This instance does not have a set value, the message .NET and PHP use. no_value_message() is unchanged, so the JSON builder still writes Unknown as the null reason in that case. --- .../fiftyone_pipeline_core/aspectproperty_value.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pipeline/fiftyone_pipeline_core/src/fiftyone_pipeline_core/aspectproperty_value.py b/pipeline/fiftyone_pipeline_core/src/fiftyone_pipeline_core/aspectproperty_value.py index 3a3f1479..4307b67d 100644 --- a/pipeline/fiftyone_pipeline_core/src/fiftyone_pipeline_core/aspectproperty_value.py +++ b/pipeline/fiftyone_pipeline_core/src/fiftyone_pipeline_core/aspectproperty_value.py @@ -21,6 +21,11 @@ # ********************************************************************* +# The message value() raises with when there is no value and no reason was +# given, the same as .NET's. +NO_VALUE_MESSAGE = "This instance does not have a set value" + + class AspectPropertyValue(object): """! @@ -66,8 +71,8 @@ def value(self): """! Get the value out of the AspectPropertyValue wrapper - Note that this will return an error (including no_value_message if set) - if there is no value. So check has_value() first to be sure. + With no value this raises, with no_value_message or, when that is + not set, NO_VALUE_MESSAGE. So check has_value() first to be sure. @rtype mixed @return the stored value @@ -77,7 +82,7 @@ def value(self): if self.__hasValue: return self.__value else: - raise Exception(self.no_value_message()) + raise Exception(self.no_value_message() or NO_VALUE_MESSAGE) def no_value_message(self):