From 9d2c5e2763ac4d67cc01a881fa59848013c35349 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Tue, 16 Dec 2025 15:06:02 -0600 Subject: [PATCH 01/12] Changed formal argument name in comparison functions from 'value' to 'other' to reduce potential confusion between the data member 'value' and the formal argument with the same name. Made all arguments in comparison functions positional. --- src/nitypes/scalar.py | 72 +++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index 82aa2763..f8646807 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -128,57 +128,57 @@ def extended_properties(self) -> ExtendedPropertyDictionary: """ return self._extended_properties - def __eq__(self, value: object, /) -> bool: - """Return self==value.""" - if not isinstance(value, self.__class__): + def __eq__(self, other: object, /) -> bool: + """Return self==other.""" + if not isinstance(other, self.__class__): return NotImplemented - return self.value == value.value and self.units == value.units + return self.value == other.value and self.units == other.units - def __gt__(self, value: Scalar[TScalar_co]) -> bool: - """Return self > value.""" - if not isinstance(value, self.__class__): + def __gt__(self, other: Scalar[TScalar_co], /) -> bool: + """Return self > other.""" + if not isinstance(other, self.__class__): return NotImplemented - self._check_units_equal_for_comparison(value.units) - if isinstance(self.value, _NUMERIC) and isinstance(value.value, _NUMERIC): - return self.value > value.value # type: ignore[no-any-return,operator] # https://github.com/python/mypy/issues/19454 - elif isinstance(self.value, str) and isinstance(value.value, str): - return self.value > value.value + self._check_units_equal_for_comparison(other.units) + if isinstance(self.value, _NUMERIC) and isinstance(other.value, _NUMERIC): + return self.value > other.value # type: ignore[no-any-return,operator] # https://github.com/python/mypy/issues/19454 + elif isinstance(self.value, str) and isinstance(other.value, str): + return self.value > other.value else: raise TypeError("Comparing Scalar objects of numeric and string types is not permitted") - def __ge__(self, value: Scalar[TScalar_co]) -> bool: - """Return self >= value.""" - if not isinstance(value, self.__class__): + def __ge__(self, other: Scalar[TScalar_co], /) -> bool: + """Return self >= other.""" + if not isinstance(other, self.__class__): return NotImplemented - self._check_units_equal_for_comparison(value.units) - if isinstance(self.value, _NUMERIC) and isinstance(value.value, _NUMERIC): - return self.value >= value.value # type: ignore[no-any-return,operator] # https://github.com/python/mypy/issues/19454 - elif isinstance(self.value, str) and isinstance(value.value, str): - return self.value >= value.value + self._check_units_equal_for_comparison(other.units) + if isinstance(self.value, _NUMERIC) and isinstance(other.value, _NUMERIC): + return self.value >= other.value # type: ignore[no-any-return,operator] # https://github.com/python/mypy/issues/19454 + elif isinstance(self.value, str) and isinstance(other.value, str): + return self.value >= other.value else: raise TypeError("Comparing Scalar objects of numeric and string types is not permitted") - def __lt__(self, value: Scalar[TScalar_co]) -> bool: - """Return self < value.""" - if not isinstance(value, self.__class__): + def __lt__(self, other: Scalar[TScalar_co], /) -> bool: + """Return self < other.""" + if not isinstance(other, self.__class__): return NotImplemented - self._check_units_equal_for_comparison(value.units) - if isinstance(self.value, _NUMERIC) and isinstance(value.value, _NUMERIC): - return self.value < value.value # type: ignore[no-any-return,operator] # https://github.com/python/mypy/issues/19454 - elif isinstance(self.value, str) and isinstance(value.value, str): - return self.value < value.value + self._check_units_equal_for_comparison(other.units) + if isinstance(self.value, _NUMERIC) and isinstance(other.value, _NUMERIC): + return self.value < other.value # type: ignore[no-any-return,operator] # https://github.com/python/mypy/issues/19454 + elif isinstance(self.value, str) and isinstance(other.value, str): + return self.value < other.value else: raise TypeError("Comparing Scalar objects of numeric and string types is not permitted") - def __le__(self, value: Scalar[TScalar_co]) -> bool: - """Return self <= value.""" - if not isinstance(value, self.__class__): + def __le__(self, other: Scalar[TScalar_co], /) -> bool: + """Return self <= other.""" + if not isinstance(other, self.__class__): return NotImplemented - self._check_units_equal_for_comparison(value.units) - if isinstance(self.value, _NUMERIC) and isinstance(value.value, _NUMERIC): - return self.value <= value.value # type: ignore[no-any-return,operator] # https://github.com/python/mypy/issues/19454 - elif isinstance(self.value, str) and isinstance(value.value, str): - return self.value <= value.value + self._check_units_equal_for_comparison(other.units) + if isinstance(self.value, _NUMERIC) and isinstance(other.value, _NUMERIC): + return self.value <= other.value # type: ignore[no-any-return,operator] # https://github.com/python/mypy/issues/19454 + elif isinstance(self.value, str) and isinstance(other.value, str): + return self.value <= other.value else: raise TypeError("Comparing Scalar objects of numeric and string types is not permitted") From 017850361126d06f0e8ef5e7636a55ca1490e3a9 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Tue, 16 Dec 2025 16:01:15 -0600 Subject: [PATCH 02/12] Refactored several exceptions with identical message into one, to eliminate duplicated string constants. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index f8646807..8033ba63 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -144,7 +144,7 @@ def __gt__(self, other: Scalar[TScalar_co], /) -> bool: elif isinstance(self.value, str) and isinstance(other.value, str): return self.value > other.value else: - raise TypeError("Comparing Scalar objects of numeric and string types is not permitted") + raise self._comparing_numeric_and_string_not_permitted() def __ge__(self, other: Scalar[TScalar_co], /) -> bool: """Return self >= other.""" @@ -156,7 +156,7 @@ def __ge__(self, other: Scalar[TScalar_co], /) -> bool: elif isinstance(self.value, str) and isinstance(other.value, str): return self.value >= other.value else: - raise TypeError("Comparing Scalar objects of numeric and string types is not permitted") + raise self._comparing_numeric_and_string_not_permitted() def __lt__(self, other: Scalar[TScalar_co], /) -> bool: """Return self < other.""" @@ -168,7 +168,7 @@ def __lt__(self, other: Scalar[TScalar_co], /) -> bool: elif isinstance(self.value, str) and isinstance(other.value, str): return self.value < other.value else: - raise TypeError("Comparing Scalar objects of numeric and string types is not permitted") + raise self._comparing_numeric_and_string_not_permitted() def __le__(self, other: Scalar[TScalar_co], /) -> bool: """Return self <= other.""" @@ -180,7 +180,7 @@ def __le__(self, other: Scalar[TScalar_co], /) -> bool: elif isinstance(self.value, str) and isinstance(other.value, str): return self.value <= other.value else: - raise TypeError("Comparing Scalar objects of numeric and string types is not permitted") + raise self._comparing_numeric_and_string_not_permitted() def __reduce__(self) -> tuple[Any, ...]: """Return object state for pickling.""" @@ -220,3 +220,6 @@ def _check_units_equal_for_comparison(self, other_units: str) -> None: """Raise a ValueError if other_units != self.units.""" if self.units != other_units: raise ValueError("Comparing Scalar objects with different units is not permitted.") + + def _comparing_numeric_and_string_not_permitted(self) -> TypeError: + return TypeError("Comparing Scalar objects of numeric and string types is not permitted") From 1f1f37f50769aef987b2465cfe565818d5574c47 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Tue, 16 Dec 2025 16:25:53 -0600 Subject: [PATCH 03/12] Added documentation about comparison. Modified old examples in the documentation based on failures I was when running 'poetry run python -m doctest src\nitypes\scalar.py -v'. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 59 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index 8033ba63..7901ea19 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -38,13 +38,64 @@ class Scalar(Generic[TScalar_co]): To construct a scalar data object, use the :class:`Scalar` class: >>> Scalar(False) - nitypes.scalar.Scalar(value=False) + scalar.Scalar(value=False) >>> Scalar(0) - nitypes.scalar.Scalar(value=0) + scalar.Scalar(value=0) >>> Scalar(5.0, 'volts') - nitypes.scalar.Scalar(value=5.0, units='volts') + scalar.Scalar(value=5.0, units='volts') >>> Scalar("value", "volts") - nitypes.scalar.Scalar(value='value', units='volts') + scalar.Scalar(value='value', units='volts') + + Comparing Scalars + ^^^^^^^^^^^^^^^^^ + You can compare scalar objects using the standard comparison operators as long as their units + are the same and their value types are compatible: + >>> s1 = Scalar(5.0, 'volts') + >>> s2 = Scalar(10.0, 'volts') + >>> s1 < s2 + True + >>> s1 <= s2 + True + >>> s1 > s2 + False + >>> s1 >= s2 + False + >>> s1 == s2 + False + >>> s3 = Scalar(5.0, 'volts') + >>> s1 == s3 + True + >>> s4 = Scalar("apple", "quantity") + >>> s5 = Scalar("banana", "quantity") + >>> s4 < s5 + True + >>> s4 <= s5 + True + >>> s4 > s5 + False + >>> s4 >= s5 + False + >>> s4 == s5 + False + >>> s6 = Scalar("apple", "quantity") + >>> s4 == s6 + True + + Attempting to compare Scalar objects with different units raises a ValueError: + >>> s1 = Scalar(5.0, 'volts') + >>> s2 = Scalar(10.0, 'amps') + >>> s1 < s2 + Traceback (most recent call last): + ... + ValueError: Comparing Scalar objects with different units is not permitted. + + Attempting to compare Scalar objects of numeric and string types raises a TypeError: + >>> s1 = Scalar(5.0, 'meters') + >>> s2 = Scalar("value", 'meters') + >>> s1 < s2 + Traceback (most recent call last): + ... + TypeError: Comparing Scalar objects of numeric and string types is not permitted Class members ^^^^^^^^^^^^^ From ef1debbb36587bd82d12739c9e40a42abdc1626b Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Tue, 16 Dec 2025 16:34:21 -0600 Subject: [PATCH 04/12] Previous removal of nitypes before some of the documentation caused automated test failure, so I reverted those few changes. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index 7901ea19..a44f6fc7 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -38,13 +38,13 @@ class Scalar(Generic[TScalar_co]): To construct a scalar data object, use the :class:`Scalar` class: >>> Scalar(False) - scalar.Scalar(value=False) + nitypes.scalar.Scalar(value=False) >>> Scalar(0) - scalar.Scalar(value=0) + nitypes.scalar.Scalar(value=0) >>> Scalar(5.0, 'volts') - scalar.Scalar(value=5.0, units='volts') + nitypes.scalar.Scalar(value=5.0, units='volts') >>> Scalar("value", "volts") - scalar.Scalar(value='value', units='volts') + nitypes.scalar.Scalar(value='value', units='volts') Comparing Scalars ^^^^^^^^^^^^^^^^^ From 60c98edfad1891281c2bc9e57d5c597de9befb79 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Tue, 16 Dec 2025 17:07:50 -0600 Subject: [PATCH 05/12] Added a blank line after a documentation heading to be consistent with previous documentation heading. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index a44f6fc7..4543cc24 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -48,6 +48,7 @@ class Scalar(Generic[TScalar_co]): Comparing Scalars ^^^^^^^^^^^^^^^^^ + You can compare scalar objects using the standard comparison operators as long as their units are the same and their value types are compatible: >>> s1 = Scalar(5.0, 'volts') From f066a121e1fc8efaf58fd5f04e86a488a12c8976 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Tue, 16 Dec 2025 17:25:10 -0600 Subject: [PATCH 06/12] Corrected help formatting errors and improved some of the examples. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index 4543cc24..8c01e3b7 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -51,8 +51,9 @@ class Scalar(Generic[TScalar_co]): You can compare scalar objects using the standard comparison operators as long as their units are the same and their value types are compatible: - >>> s1 = Scalar(5.0, 'volts') - >>> s2 = Scalar(10.0, 'volts') + + >>> s1 = Scalar(5.0, 'V') + >>> s2 = Scalar(10.0, 'V') >>> s1 < s2 True >>> s1 <= s2 @@ -63,7 +64,7 @@ class Scalar(Generic[TScalar_co]): False >>> s1 == s2 False - >>> s3 = Scalar(5.0, 'volts') + >>> s3 = Scalar(5.0, 'V') >>> s1 == s3 True >>> s4 = Scalar("apple", "quantity") @@ -83,14 +84,16 @@ class Scalar(Generic[TScalar_co]): True Attempting to compare Scalar objects with different units raises a ValueError: - >>> s1 = Scalar(5.0, 'volts') - >>> s2 = Scalar(10.0, 'amps') + + >>> s1 = Scalar(0.5, 'V') + >>> s2 = Scalar(500, 'mV') >>> s1 < s2 Traceback (most recent call last): ... ValueError: Comparing Scalar objects with different units is not permitted. Attempting to compare Scalar objects of numeric and string types raises a TypeError: + >>> s1 = Scalar(5.0, 'meters') >>> s2 = Scalar("value", 'meters') >>> s1 < s2 From 8729d269af7d3ab611d4d57522e6c9e11ea4d47e Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Tue, 16 Dec 2025 19:06:14 -0600 Subject: [PATCH 07/12] Added period at the end of a sentence in an exception message, to make it consistent with other similar sentences. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index 8c01e3b7..cb5caa6e 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -99,7 +99,7 @@ class Scalar(Generic[TScalar_co]): >>> s1 < s2 Traceback (most recent call last): ... - TypeError: Comparing Scalar objects of numeric and string types is not permitted + TypeError: Comparing Scalar objects of numeric and string types is not permitted. Class members ^^^^^^^^^^^^^ @@ -277,4 +277,4 @@ def _check_units_equal_for_comparison(self, other_units: str) -> None: raise ValueError("Comparing Scalar objects with different units is not permitted.") def _comparing_numeric_and_string_not_permitted(self) -> TypeError: - return TypeError("Comparing Scalar objects of numeric and string types is not permitted") + return TypeError("Comparing Scalar objects of numeric and string types is not permitted.") From e892647c7a49674c67ac8c88a70e8346b76ea502 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Wed, 17 Dec 2025 07:53:14 -0600 Subject: [PATCH 08/12] Improved class documentation per my own PR feedback. Also made two other petty documentation improvements. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 80 ++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index cb5caa6e..ffacabc8 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -46,57 +46,75 @@ class Scalar(Generic[TScalar_co]): >>> Scalar("value", "volts") nitypes.scalar.Scalar(value='value', units='volts') - Comparing Scalars - ^^^^^^^^^^^^^^^^^ + Comparing Scalar Objects + ^^^^^^^^^^^^^^^^^^^^^^^^ - You can compare scalar objects using the standard comparison operators as long as their units - are the same and their value types are compatible: + You can compare scalar objects of compatible types and with identical units + using the standard comparison operators (`<`, `<=`, `>`, `>=`, `==`, and `!=`). - >>> s1 = Scalar(5.0, 'V') - >>> s2 = Scalar(10.0, 'V') - >>> s1 < s2 + Here are some examples of comparing numeric scalar objects with identical units: + + >>> voltage1 = Scalar(5.0, 'V') + >>> voltage2 = Scalar(10.0, 'V') + >>> voltage1 < voltage2 True - >>> s1 <= s2 + >>> voltage1 <= voltage2 True - >>> s1 > s2 + >>> voltage1 > voltage2 False - >>> s1 >= s2 + >>> voltage1 >= voltage2 False - >>> s1 == s2 + >>> voltage1 == voltage2 False - >>> s3 = Scalar(5.0, 'V') - >>> s1 == s3 + >>> voltage1 != voltage2 + True + >>> voltage3 = Scalar(5.0, 'V') + >>> voltage1 == voltage3 True - >>> s4 = Scalar("apple", "quantity") - >>> s5 = Scalar("banana", "quantity") - >>> s4 < s5 + + Here are some examples of comparing string scalar objects with identical units: + + >>> fruit1 = Scalar("apple") + >>> fruit2 = Scalar("banana") + >>> fruit1 < fruit2 True - >>> s4 <= s5 + >>> fruit1 <= fruit2 True - >>> s4 > s5 + >>> fruit1 > fruit2 False - >>> s4 >= s5 + >>> fruit1 >= fruit2 False - >>> s4 == s5 + >>> fruit1 == fruit2 False - >>> s6 = Scalar("apple", "quantity") - >>> s4 == s6 + >>> fruit1 != fruit2 True + >>> fruit3 = Scalar("apple") + >>> fruit1 == fruit3 + True + + If you compare scalar objects with compatible types and different units using the + equal to (`==`) operator, the result will be false. + If you use the not equal to (`!=`) operator, the result will be true. + Using other comparison operators (`<`, `<=`, `>`, `>=`) will raise a ValueError. - Attempting to compare Scalar objects with different units raises a ValueError: + Here are some examples: - >>> s1 = Scalar(0.5, 'V') - >>> s2 = Scalar(500, 'mV') - >>> s1 < s2 + >>> voltage1 = Scalar(0.5, 'V') + >>> voltage2 = Scalar(500, 'mV') + >>> voltage1 == voltage2 + False + >>> voltage1 != voltage2 + True + >>> voltage1 < voltage2 Traceback (most recent call last): ... ValueError: Comparing Scalar objects with different units is not permitted. Attempting to compare Scalar objects of numeric and string types raises a TypeError: - >>> s1 = Scalar(5.0, 'meters') - >>> s2 = Scalar("value", 'meters') - >>> s1 < s2 + >>> length1 = Scalar(5.0, 'meters') + >>> length2 = Scalar("five", 'meters') + >>> length1 < length2 Traceback (most recent call last): ... TypeError: Comparing Scalar objects of numeric and string types is not permitted. @@ -184,7 +202,7 @@ def extended_properties(self) -> ExtendedPropertyDictionary: return self._extended_properties def __eq__(self, other: object, /) -> bool: - """Return self==other.""" + """Return self == other.""" if not isinstance(other, self.__class__): return NotImplemented return self.value == other.value and self.units == other.units @@ -272,7 +290,7 @@ def __str__(self) -> str: return value_str def _check_units_equal_for_comparison(self, other_units: str) -> None: - """Raise a ValueError if other_units != self.units.""" + """Raise a ValueError if self.units != other_units.""" if self.units != other_units: raise ValueError("Comparing Scalar objects with different units is not permitted.") From 078df3af7a06c68cf20d86b45d98468d79969830 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Wed, 17 Dec 2025 08:02:26 -0600 Subject: [PATCH 09/12] Fixed an incorrect statement in the documentation. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index ffacabc8..a570742c 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -72,7 +72,7 @@ class Scalar(Generic[TScalar_co]): >>> voltage1 == voltage3 True - Here are some examples of comparing string scalar objects with identical units: + Here are some examples of comparing string scalar objects without units: >>> fruit1 = Scalar("apple") >>> fruit2 = Scalar("banana") From dc7049a797aea50490404334d7c5bf803283a6b6 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Thu, 18 Dec 2025 10:52:15 -0600 Subject: [PATCH 10/12] Addressed PR feedback provided by bkeryan. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 86 ++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 58 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index a570742c..87b80199 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -50,76 +50,46 @@ class Scalar(Generic[TScalar_co]): ^^^^^^^^^^^^^^^^^^^^^^^^ You can compare scalar objects of compatible types and with identical units - using the standard comparison operators (`<`, `<=`, `>`, `>=`, `==`, and `!=`). + using the standard comparison operators (``<``, ``<=``, ``>``, ``>=``, ``==``, and ``!=``). Here are some examples of comparing numeric scalar objects with identical units: - >>> voltage1 = Scalar(5.0, 'V') - >>> voltage2 = Scalar(10.0, 'V') - >>> voltage1 < voltage2 + >>> Scalar(5.0, 'V') < Scalar(10.0, 'V') True - >>> voltage1 <= voltage2 - True - >>> voltage1 > voltage2 - False - >>> voltage1 >= voltage2 + >>> Scalar(5.0, 'V') >= Scalar(10.0, 'V') False - >>> voltage1 == voltage2 - False - >>> voltage1 != voltage2 - True - >>> voltage3 = Scalar(5.0, 'V') - >>> voltage1 == voltage3 + >>> Scalar(5.0, 'V') == Scalar(5.0, 'V') True Here are some examples of comparing string scalar objects without units: - >>> fruit1 = Scalar("apple") - >>> fruit2 = Scalar("banana") - >>> fruit1 < fruit2 + >>> Scalar("apple") < Scalar("banana") True - >>> fruit1 <= fruit2 - True - >>> fruit1 > fruit2 - False - >>> fruit1 >= fruit2 - False - >>> fruit1 == fruit2 + >>> Scalar("apple") < Scalar("Banana") False - >>> fruit1 != fruit2 - True - >>> fruit3 = Scalar("apple") - >>> fruit1 == fruit3 - True - If you compare scalar objects with compatible types and different units using the - equal to (`==`) operator, the result will be false. - If you use the not equal to (`!=`) operator, the result will be true. - Using other comparison operators (`<`, `<=`, `>`, `>=`) will raise a ValueError. + Equality comparison operators (``==`` and ``!=``) are always supported. - Here are some examples: + Here are some examples of comparing scalar objects with different units: - >>> voltage1 = Scalar(0.5, 'V') - >>> voltage2 = Scalar(500, 'mV') - >>> voltage1 == voltage2 + >>> Scalar(0.5, 'V') == Scalar(500, 'mV') False - >>> voltage1 != voltage2 + >>> Scalar(0.5, 'V') != Scalar(500, 'mV') True - >>> voltage1 < voltage2 - Traceback (most recent call last): - ... - ValueError: Comparing Scalar objects with different units is not permitted. - Attempting to compare Scalar objects of numeric and string types raises a TypeError: + Here is an example of comparing numeric and string scalar objects: + + >>> Scalar(5.0, 'V') == Scalar("5.0", 'V') + False + + Order comparison operators (``<``, ``<=``, ``>``, and ``>=``) raise ``TypeError`` exception + if the combination of types is not supported, such as when comparing + a numeric scalar object and a string scalar object. - >>> length1 = Scalar(5.0, 'meters') - >>> length2 = Scalar("five", 'meters') - >>> length1 < length2 - Traceback (most recent call last): - ... - TypeError: Comparing Scalar objects of numeric and string types is not permitted. + Order comparison operators (``<``, ``<=``, ``>``, and ``>=``) raise ``ValueError`` exception + if the units are different. - Class members + Class Members ^^^^^^^^^^^^^ """ @@ -217,7 +187,7 @@ def __gt__(self, other: Scalar[TScalar_co], /) -> bool: elif isinstance(self.value, str) and isinstance(other.value, str): return self.value > other.value else: - raise self._comparing_numeric_and_string_not_permitted() + raise _comparing_numeric_and_string_not_permitted() def __ge__(self, other: Scalar[TScalar_co], /) -> bool: """Return self >= other.""" @@ -229,7 +199,7 @@ def __ge__(self, other: Scalar[TScalar_co], /) -> bool: elif isinstance(self.value, str) and isinstance(other.value, str): return self.value >= other.value else: - raise self._comparing_numeric_and_string_not_permitted() + raise _comparing_numeric_and_string_not_permitted() def __lt__(self, other: Scalar[TScalar_co], /) -> bool: """Return self < other.""" @@ -241,7 +211,7 @@ def __lt__(self, other: Scalar[TScalar_co], /) -> bool: elif isinstance(self.value, str) and isinstance(other.value, str): return self.value < other.value else: - raise self._comparing_numeric_and_string_not_permitted() + raise _comparing_numeric_and_string_not_permitted() def __le__(self, other: Scalar[TScalar_co], /) -> bool: """Return self <= other.""" @@ -253,7 +223,7 @@ def __le__(self, other: Scalar[TScalar_co], /) -> bool: elif isinstance(self.value, str) and isinstance(other.value, str): return self.value <= other.value else: - raise self._comparing_numeric_and_string_not_permitted() + raise _comparing_numeric_and_string_not_permitted() def __reduce__(self) -> tuple[Any, ...]: """Return object state for pickling.""" @@ -290,9 +260,9 @@ def __str__(self) -> str: return value_str def _check_units_equal_for_comparison(self, other_units: str) -> None: - """Raise a ValueError if self.units != other_units.""" if self.units != other_units: raise ValueError("Comparing Scalar objects with different units is not permitted.") - def _comparing_numeric_and_string_not_permitted(self) -> TypeError: - return TypeError("Comparing Scalar objects of numeric and string types is not permitted.") + +def _comparing_numeric_and_string_not_permitted() -> TypeError: + return TypeError("Comparing Scalar objects of numeric and string types is not permitted.") From ef1b133bbe1f53fe34676f18ab731486b6eec6a8 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Thu, 18 Dec 2025 11:56:32 -0600 Subject: [PATCH 11/12] I reorganized comparison section based on my own PR feedback inspired by a comment from bkeryan. I like this organization better than what we had before. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 75 ++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index 87b80199..5fc34b38 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -49,45 +49,68 @@ class Scalar(Generic[TScalar_co]): Comparing Scalar Objects ^^^^^^^^^^^^^^^^^^^^^^^^ - You can compare scalar objects of compatible types and with identical units - using the standard comparison operators (``<``, ``<=``, ``>``, ``>=``, ``==``, and ``!=``). + You can compare scalar objects using standard comparison + operators: ``<``, ``<=``, ``>``, ``>=``, ``==``, and ``!=``. + Detailed descriptions of operator behaviors are provided below. - Here are some examples of comparing numeric scalar objects with identical units: + Equality Comparison Operators + ----------------------------- - >>> Scalar(5.0, 'V') < Scalar(10.0, 'V') + Equality comparison operators (``==`` and ``!=``) are always supported and behave as follows: + + - Comparison of scalar objects with compatible types and identical units results + in ``True`` or ``False`` based on the comparison of scalar object values. + - Comparison of scalar objects with incompatible types (such as numeric and string) + results in inequality. + - Comparison of scalar objects with different units results in inequality. + + Examples: + + >>> Scalar(5.0, 'V') == Scalar(5.0, 'V') # Numeric scalars with identical values and units True - >>> Scalar(5.0, 'V') >= Scalar(10.0, 'V') + >>> Scalar(5.0, 'V') == Scalar(12.3, 'V') # Numeric scalars with identical units False - >>> Scalar(5.0, 'V') == Scalar(5.0, 'V') + >>> Scalar(5.0, 'V') != Scalar(12.3, 'V') # Numeric scalars with identical units True + >>> Scalar("apple") == Scalar("banana") # String scalars + False + >>> Scalar("apple") == Scalar("Apple") # String scalars - note case sensitivity + False + >>> Scalar(0.5, 'V') == Scalar(500, 'mV') # Numeric scalars with different units + False + >>> Scalar(5.0, 'V') == Scalar("5.0", 'V') # Comparison of a numeric and a string scalar + False - Here are some examples of comparing string scalar objects without units: + Order Comparison Operators + -------------------------- - >>> Scalar("apple") < Scalar("banana") - True - >>> Scalar("apple") < Scalar("Banana") - False + Order comparison operators (``<``, ``<=``, ``>``, and ``>=``) behave as follows: - Equality comparison operators (``==`` and ``!=``) are always supported. + - Comparison of scalar objects with compatible types and identical units results + in ``True`` or ``False`` based on the comparison of scalar object values. + - Comparison of scalar objects with incompatible types (such as numeric and string) + is not permitted and will raise a ``TypeError`` exception. + - Comparison of scalar objects with compatible types and different units + is not permitted and will raise a ``ValueError`` exception. - Here are some examples of comparing scalar objects with different units: + Examples: - >>> Scalar(0.5, 'V') == Scalar(500, 'mV') + >>> Scalar(5.0, 'V') < Scalar(10.0, 'V') # Numeric scalars with identical units + True + >>> Scalar(5.0, 'V') >= Scalar(10.0, 'V') # Numeric scalars with identical units False - >>> Scalar(0.5, 'V') != Scalar(500, 'mV') + >>> Scalar("apple") < Scalar("banana") # String scalars True - - Here is an example of comparing numeric and string scalar objects: - - >>> Scalar(5.0, 'V') == Scalar("5.0", 'V') + >>> Scalar("apple") < Scalar("Banana") # String scalars - note case sensitivity False - - Order comparison operators (``<``, ``<=``, ``>``, and ``>=``) raise ``TypeError`` exception - if the combination of types is not supported, such as when comparing - a numeric scalar object and a string scalar object. - - Order comparison operators (``<``, ``<=``, ``>``, and ``>=``) raise ``ValueError`` exception - if the units are different. + >>> Scalar(5.0, 'V') < Scalar("5.0", 'V') # Comparison of a numeric and a string scalar + Traceback (most recent call last): + ... + TypeError: Comparing Scalar objects of numeric and string types is not permitted. + >>> Scalar(0.5, 'V') < Scalar(500, 'mV') # Numeric scalars with different units + Traceback (most recent call last): + ... + ValueError: Comparing Scalar objects with different units is not permitted. Class Members ^^^^^^^^^^^^^ From b30fc9abf48adc3ff5416e10aee353af965ea516 Mon Sep 17 00:00:00 2001 From: Kosta Ilic Date: Thu, 18 Dec 2025 13:06:18 -0600 Subject: [PATCH 12/12] Fixed a linting problem I don't fully understand - I was not able to penetrate the arcane error message. Signed-off-by: Kosta Ilic --- src/nitypes/scalar.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nitypes/scalar.py b/src/nitypes/scalar.py index 5fc34b38..233c2c0a 100644 --- a/src/nitypes/scalar.py +++ b/src/nitypes/scalar.py @@ -64,7 +64,7 @@ class Scalar(Generic[TScalar_co]): results in inequality. - Comparison of scalar objects with different units results in inequality. - Examples: + Here are a few examples: >>> Scalar(5.0, 'V') == Scalar(5.0, 'V') # Numeric scalars with identical values and units True @@ -93,7 +93,7 @@ class Scalar(Generic[TScalar_co]): - Comparison of scalar objects with compatible types and different units is not permitted and will raise a ``ValueError`` exception. - Examples: + Here are a few examples: >>> Scalar(5.0, 'V') < Scalar(10.0, 'V') # Numeric scalars with identical units True