Skip to content

Commit

Permalink
Fix negative xsd range edge cases (#178)
Browse files Browse the repository at this point in the history
The current implementation uses the `abs()` function to check
that the value is inside the range.
However, the range is not symmetric.
For example, for a [byte](https://www.w3.org/TR/xmlschema11-2/#byte),
which is between [-128, 127],
the value of
[maxInclusive](https://www.w3.org/TR/xmlschema11-2/#dt-maxInclusive)
should be 127,
and [minInclusive](https://www.w3.org/TR/xmlschema11-2/#dt-minInclusive)
 should be -128.
  • Loading branch information
mhrimaz authored and s-heppner committed Dec 11, 2023
1 parent 662ccf6 commit a550f76
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
12 changes: 8 additions & 4 deletions basyx/aas/model/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,31 +261,35 @@ class Float(float):
class Long(int):
def __new__(cls, *args, **kwargs):
res = int.__new__(cls, *args, **kwargs)
if abs(res) > 2**63-1:
# [-9223372036854775808, 9223372036854775807]
if res > 2**63-1 or res < -2**63:
raise ValueError("{} is out of the allowed range for type {}".format(res, cls.__name__))
return res


class Int(int):
def __new__(cls, *args, **kwargs):
res = int.__new__(cls, *args, **kwargs)
if abs(res) > 2**31-1:
# [-2147483648, 2147483647]
if res > 2**31-1 or res < -2**31:
raise ValueError("{} is out of the allowed range for type {}".format(res, cls.__name__))
return res


class Short(int):
def __new__(cls, *args, **kwargs):
res = int.__new__(cls, *args, **kwargs)
if abs(res) > 2**15-1:
# [-32768, 32767]
if res > 2**15-1 or res < -2**15:
raise ValueError("{} is out of the allowed range for type {}".format(res, cls.__name__))
return res


class Byte(int):
def __new__(cls, *args, **kwargs):
res = int.__new__(cls, *args, **kwargs)
if abs(res) > 2**7-1:
# [-128,127]
if res > 2**7-1 or res < -2**7:
raise ValueError("{} is out of the allowed range for type {}".format(res, cls.__name__))
return res

Expand Down
12 changes: 12 additions & 0 deletions test/model/test_datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,23 @@ def test_parse_int(self) -> None:
self.assertEqual(5, model.datatypes.from_xsd("5", model.datatypes.Integer))
self.assertEqual(6, model.datatypes.from_xsd("6", model.datatypes.Byte))
self.assertEqual(7, model.datatypes.from_xsd("7", model.datatypes.NonNegativeInteger))
self.assertEqual(8, model.datatypes.from_xsd("8", model.datatypes.Long))
self.assertEqual(9, model.datatypes.from_xsd("9", model.datatypes.Int))
self.assertEqual(10, model.datatypes.from_xsd("10", model.datatypes.Short))
self.assertEqual(-123456789012345678901234567890,
model.datatypes.from_xsd("-123456789012345678901234567890", model.datatypes.Integer))
self.assertEqual(2147483647, model.datatypes.from_xsd("2147483647", model.datatypes.Int))
self.assertEqual(-2147483648, model.datatypes.from_xsd("-2147483648", model.datatypes.Int))
self.assertEqual(-32768, model.datatypes.from_xsd("-32768", model.datatypes.Short))
self.assertEqual(-128, model.datatypes.from_xsd("-128", model.datatypes.Byte))
self.assertEqual(-9223372036854775808,
model.datatypes.from_xsd("-9223372036854775808", model.datatypes.Long))

def test_serialize_int(self) -> None:
self.assertEqual("5", model.datatypes.xsd_repr(model.datatypes.Integer(5)))
self.assertEqual("6", model.datatypes.xsd_repr(model.datatypes.Byte(6)))
self.assertEqual("7", model.datatypes.xsd_repr(model.datatypes.NonNegativeInteger(7)))
self.assertEqual("-128", model.datatypes.xsd_repr(model.datatypes.Byte(-128)))

def test_range_error(self) -> None:
with self.assertRaises(ValueError) as cm:
Expand Down

0 comments on commit a550f76

Please sign in to comment.