Skip to content

Commit 33148f3

Browse files
committed
fix(api): Update NumericRange handling to use half-open intervals
Changes NumericRange boundaries to use half-open intervals [lower, upper). Updates logic in data utilities, and corresponding tests to reflect this standard. Ensures consistency across range handling and validation outputs. Fixes #20471
1 parent f23eb53 commit 33148f3

File tree

3 files changed

+18
-11
lines changed

3 files changed

+18
-11
lines changed

netbox/netbox/api/fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def to_internal_value(self, data):
169169
if type(data[0]) is not int or type(data[1]) is not int:
170170
raise ValidationError(_("Range boundaries must be defined as integers."))
171171

172-
return NumericRange(data[0], data[1], bounds='[]')
172+
return NumericRange(data[0], data[1] + 1, bounds='[)')
173173

174174
def to_representation(self, instance):
175175
return instance.lower, instance.upper - 1

netbox/utilities/data.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,16 @@ def ranges_to_string(ranges):
152152

153153
def string_to_ranges(value):
154154
"""
155-
Given a string in the format "1-100, 200-300" return an list of NumericRanges. Intended for use with ArrayField.
156-
For example:
157-
"1-99,200-299" => [NumericRange(1, 100), NumericRange(200, 300)]
155+
Converts a string representation of numeric ranges into a list of NumericRange objects.
156+
157+
This function parses a string containing numeric values and ranges separated by commas (e.g.,
158+
"1-5,8,10-12") and converts it into a list of NumericRange objects.
159+
In the case of a single integer, it is treated as a range where the start and end
160+
are equal. The returned ranges are represented as half-open intervals [lower, upper).
161+
Intended for use with ArrayField.
162+
163+
Example:
164+
"1-5,8,10-12" => [NumericRange(1, 6), NumericRange(8, 9), NumericRange(10, 13)]
158165
"""
159166
if not value:
160167
return None
@@ -172,5 +179,5 @@ def string_to_ranges(value):
172179
upper = dash_range[1]
173180
else:
174181
return None
175-
values.append(NumericRange(int(lower), int(upper), bounds='[]'))
182+
values.append(NumericRange(int(lower), int(upper) + 1, bounds='[)'))
176183
return values

netbox/utilities/tests/test_data.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,18 @@ def test_string_to_ranges(self):
6161
self.assertEqual(
6262
string_to_ranges('10-19, 30-39, 100-199'),
6363
[
64-
NumericRange(10, 19, bounds='[]'), # 10-19
65-
NumericRange(30, 39, bounds='[]'), # 30-39
66-
NumericRange(100, 199, bounds='[]'), # 100-199
64+
NumericRange(10, 20, bounds='[)'), # 10-20
65+
NumericRange(30, 40, bounds='[)'), # 30-40
66+
NumericRange(100, 200, bounds='[)'), # 100-200
6767
]
6868
)
6969

7070
self.assertEqual(
7171
string_to_ranges('1-2, 5, 10-12'),
7272
[
73-
NumericRange(1, 2, bounds='[]'), # 1-2
74-
NumericRange(5, 5, bounds='[]'), # 5-5
75-
NumericRange(10, 12, bounds='[]'), # 10-12
73+
NumericRange(1, 3, bounds='[)'), # 1-3
74+
NumericRange(5, 6, bounds='[)'), # 5-6
75+
NumericRange(10, 13, bounds='[)'), # 10-13
7676
]
7777
)
7878

0 commit comments

Comments
 (0)