Skip to content

Commit

Permalink
Merge pull request #3062 from jsiirola/set-index-error
Browse files Browse the repository at this point in the history
Clarify errors raised by accessing Sets by positional index
  • Loading branch information
blnicho authored Dec 19, 2023
2 parents 3bab26c + 3ad12d6 commit dbff7d1
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 41 deletions.
58 changes: 28 additions & 30 deletions pyomo/core/base/set.py
Original file line number Diff line number Diff line change
Expand Up @@ -1584,28 +1584,26 @@ def _to_0_based_index(self, item):
# implementation does not guarantee that the index is valid (it
# could be outside of abs(i) <= len(self)).
try:
if item != int(item):
raise IndexError(
"%s indices must be integers, not %s"
% (self.name, type(item).__name__)
)
item = int(item)
_item = int(item)
if item != _item:
raise IndexError()
except:
raise IndexError(
"%s indices must be integers, not %s" % (self.name, type(item).__name__)
)

if item >= 1:
return item - 1
elif item < 0:
item += len(self)
if item < 0:
raise IndexError("%s index out of range" % (self.name,))
return item
f"Set '{self.name}' positional indices must be integers, "
f"not {type(item).__name__}"
) from None

if _item >= 1:
return _item - 1
elif _item < 0:
_item += len(self)
if _item < 0:
raise IndexError(f"{self.name} index out of range")
return _item
else:
raise IndexError(
"Pyomo Sets are 1-indexed: valid index values for Sets are "
"[1 .. len(Set)] or [-1 .. -len(Set)]"
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
"index values are [1 .. len(Set)] or [-1 .. -len(Set)]"
)


Expand Down Expand Up @@ -1683,7 +1681,7 @@ def at(self, index):
try:
return self._ordered_values[i]
except IndexError:
raise IndexError("%s index out of range" % (self.name))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
"""
Expand Down Expand Up @@ -2023,7 +2021,7 @@ def __init__(
filter=None,
validate=None,
name=None,
doc=None
doc=None,
):
...

Expand Down Expand Up @@ -2545,7 +2543,7 @@ def at(self, index):
try:
return self._ref[i]
except IndexError:
raise IndexError("%s index out of range" % (self.name))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
# The bulk of single-value set members are stored as scalars.
Expand Down Expand Up @@ -2686,7 +2684,7 @@ def at(self, index):
if not idx:
return ans
idx -= 1
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range")

def ord(self, item):
if len(self._ranges) == 1:
Expand Down Expand Up @@ -2861,7 +2859,7 @@ def __init__(
filter=None,
validate=None,
name=None,
doc=None
doc=None,
):
...

Expand All @@ -2878,7 +2876,7 @@ def __init__(
filter=None,
validate=None,
name=None,
doc=None
doc=None,
):
...

Expand All @@ -2892,7 +2890,7 @@ def __init__(
filter=None,
validate=None,
name=None,
doc=None
doc=None,
):
...

Expand Down Expand Up @@ -3505,7 +3503,7 @@ def at(self, index):
if val not in self._sets[0]:
idx -= 1
except StopIteration:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range") from None
return val

def ord(self, item):
Expand Down Expand Up @@ -3642,7 +3640,7 @@ def at(self, index):
idx -= 1
return next(_iter)
except StopIteration:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
"""
Expand Down Expand Up @@ -3736,7 +3734,7 @@ def at(self, index):
idx -= 1
return next(_iter)
except StopIteration:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
"""
Expand Down Expand Up @@ -3846,7 +3844,7 @@ def at(self, index):
idx -= 1
return next(_iter)
except StopIteration:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
"""
Expand Down Expand Up @@ -4128,7 +4126,7 @@ def at(self, index):
i -= 1
_ord[i], _idx = _idx % _ord[i], _idx // _ord[i]
if _idx:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range")
ans = tuple(s.at(i + 1) for s, i in zip(self._sets, _ord))
if FLATTEN_CROSS_PRODUCT and normalize_index.flatten and self.dimen != len(ans):
return self._flatten_product(ans)
Expand Down
22 changes: 12 additions & 10 deletions pyomo/core/tests/unit/test_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -1530,8 +1530,8 @@ def test_ordered_setof(self):
self.assertEqual(i[-1], 0)
with self.assertRaisesRegex(
IndexError,
"valid index values for Sets are "
r"\[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
r"index values are \[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
):
i[0]
with self.assertRaisesRegex(IndexError, "OrderedSetOf index out of range"):
Expand Down Expand Up @@ -1589,8 +1589,8 @@ def test_ordered_setof(self):
self.assertEqual(i[-1], 0)
with self.assertRaisesRegex(
IndexError,
"valid index values for Sets are "
r"\[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
r"index values are \[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
):
i[0]
with self.assertRaisesRegex(IndexError, "OrderedSetOf index out of range"):
Expand Down Expand Up @@ -1752,8 +1752,8 @@ def test_ord_index(self):
self.assertEqual(r[i + 1], v)
with self.assertRaisesRegex(
IndexError,
"valid index values for Sets are "
r"\[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
r"index values are \[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
):
r[0]
with self.assertRaisesRegex(
Expand All @@ -1769,8 +1769,8 @@ def test_ord_index(self):
self.assertEqual(r[i + 1], v)
with self.assertRaisesRegex(
IndexError,
"valid index values for Sets are "
r"\[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
r"index values are \[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
):
r[0]
with self.assertRaisesRegex(
Expand Down Expand Up @@ -4191,10 +4191,12 @@ def test_indexing(self):
m.I = [1, 3, 2]
self.assertEqual(m.I[2], 3)
with self.assertRaisesRegex(
IndexError, "I indices must be integers, not float"
IndexError, "Set 'I' positional indices must be integers, not float"
):
m.I[2.5]
with self.assertRaisesRegex(IndexError, "I indices must be integers, not str"):
with self.assertRaisesRegex(
IndexError, "Set 'I' positional indices must be integers, not str"
):
m.I['a']

def test_add_filter_validate(self):
Expand Down
4 changes: 3 additions & 1 deletion pyomo/core/tests/unit/test_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3395,7 +3395,9 @@ def test_getitem(self):
with self.assertRaisesRegex(RuntimeError, ".*before it has been constructed"):
a[0]
a.construct()
with self.assertRaisesRegex(IndexError, "Pyomo Sets are 1-indexed"):
with self.assertRaisesRegex(
IndexError, "Accessing Pyomo Sets by position is 1-based"
):
a[0]
self.assertEqual(a[1], 2)

Expand Down

0 comments on commit dbff7d1

Please sign in to comment.