fix(api): Update NumericRange handling to use half-open intervals (#20478)

This commit is contained in:
Martin Hauser 2025-10-07 18:01:29 +02:00 committed by GitHub
parent 51528ae429
commit b7cae04572
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 11 deletions

View File

@ -169,7 +169,7 @@ class IntegerRangeSerializer(serializers.Serializer):
if type(data[0]) is not int or type(data[1]) is not int: if type(data[0]) is not int or type(data[1]) is not int:
raise ValidationError(_("Range boundaries must be defined as integers.")) raise ValidationError(_("Range boundaries must be defined as integers."))
return NumericRange(data[0], data[1], bounds='[]') return NumericRange(data[0], data[1] + 1, bounds='[)')
def to_representation(self, instance): def to_representation(self, instance):
return instance.lower, instance.upper - 1 return instance.lower, instance.upper - 1

View File

@ -161,9 +161,16 @@ def ranges_to_string(ranges):
def string_to_ranges(value): def string_to_ranges(value):
""" """
Given a string in the format "1-100, 200-300" return an list of NumericRanges. Intended for use with ArrayField. Converts a string representation of numeric ranges into a list of NumericRange objects.
For example:
"1-99,200-299" => [NumericRange(1, 100), NumericRange(200, 300)] This function parses a string containing numeric values and ranges separated by commas (e.g.,
"1-5,8,10-12") and converts it into a list of NumericRange objects.
In the case of a single integer, it is treated as a range where the start and end
are equal. The returned ranges are represented as half-open intervals [lower, upper).
Intended for use with ArrayField.
Example:
"1-5,8,10-12" => [NumericRange(1, 6), NumericRange(8, 9), NumericRange(10, 13)]
""" """
if not value: if not value:
return None return None
@ -181,5 +188,5 @@ def string_to_ranges(value):
upper = dash_range[1] upper = dash_range[1]
else: else:
return None return None
values.append(NumericRange(int(lower), int(upper), bounds='[]')) values.append(NumericRange(int(lower), int(upper) + 1, bounds='[)'))
return values return values

View File

@ -61,18 +61,18 @@ class RangeFunctionsTestCase(TestCase):
self.assertEqual( self.assertEqual(
string_to_ranges('10-19, 30-39, 100-199'), string_to_ranges('10-19, 30-39, 100-199'),
[ [
NumericRange(10, 19, bounds='[]'), # 10-19 NumericRange(10, 20, bounds='[)'), # 10-20
NumericRange(30, 39, bounds='[]'), # 30-39 NumericRange(30, 40, bounds='[)'), # 30-40
NumericRange(100, 199, bounds='[]'), # 100-199 NumericRange(100, 200, bounds='[)'), # 100-200
] ]
) )
self.assertEqual( self.assertEqual(
string_to_ranges('1-2, 5, 10-12'), string_to_ranges('1-2, 5, 10-12'),
[ [
NumericRange(1, 2, bounds='[]'), # 1-2 NumericRange(1, 3, bounds='[)'), # 1-3
NumericRange(5, 5, bounds='[]'), # 5-5 NumericRange(5, 6, bounds='[)'), # 5-6
NumericRange(10, 12, bounds='[]'), # 10-12 NumericRange(10, 13, bounds='[)'), # 10-13
] ]
) )