Skip to content

Commit 7fc5de4

Browse files
authored
Improve error message for unsupported attribute for bridges (#2329)
1 parent b323a79 commit 7fc5de4

File tree

3 files changed

+55
-36
lines changed

3 files changed

+55
-36
lines changed

src/Bridges/bridge.jl

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ function MOI.supports(
119119
return false
120120
end
121121

122+
function _attribute_error_message(attr, ::Type{B}, action) where {B}
123+
return "Bridge of type `$(nameof(B))` does not support " *
124+
"$action the attribute `$attr`. If you encountered this error " *
125+
"unexpectedly, it probably means your model has been " *
126+
"reformulated using the bridge, and you are attempting to query " *
127+
"an attribute that we haven't implemented yet for this bridge. " *
128+
"Please open an issue at https://github.com/jump-dev/MathOptInterface.jl/issues/new " *
129+
"and provide a reproducible example explaining what you were " *
130+
"trying to do."
131+
end
132+
122133
"""
123134
function MOI.get(
124135
model::MOI.ModelLike,
@@ -134,18 +145,8 @@ function MOI.get(
134145
attr::MOI.AbstractConstraintAttribute,
135146
bridge::AbstractBridge,
136147
)
137-
return throw(
138-
ArgumentError(
139-
"Bridge of type `$(typeof(bridge))` does not support accessing " *
140-
"the attribute `$attr`. If you encountered this error " *
141-
"unexpectedly, it probably means your model has been " *
142-
"reformulated using the bridge, and you are attempting to query " *
143-
"an attribute that we haven't implemented yet for this bridge. " *
144-
"Please open an issue at https://github.com/jump-dev/MathOptInterface.jl/issues/new " *
145-
"and provide a reproducible example explaining what you were " *
146-
"trying to do.",
147-
),
148-
)
148+
message = _attribute_error_message(attr, typeof(bridge), "accessing")
149+
return throw(ArgumentError(message))
149150
end
150151

151152
function MOI.get(
@@ -173,12 +174,14 @@ function MOI.set(
173174
model::MOI.ModelLike,
174175
attr::MOI.AbstractConstraintAttribute,
175176
bridge::AbstractBridge,
176-
value,
177+
::Any,
177178
)
179+
message =
180+
_attribute_error_message(attr, typeof(bridge), "setting a value for")
178181
if MOI.is_copyable(attr) && !MOI.supports(model, attr, typeof(bridge))
179-
throw(MOI.UnsupportedAttribute(attr))
182+
return throw(MOI.UnsupportedAttribute(attr, message))
180183
else
181-
throw(MOI.SetAttributeNotAllowed(attr))
184+
return throw(MOI.SetAttributeNotAllowed(attr, message))
182185
end
183186
end
184187

test/Bridges/Constraint/bridge.jl

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,26 @@ struct DummyBridge <: MOI.Bridges.Constraint.AbstractBridge end
2626
function test_AbstractBridge()
2727
model = MOI.Utilities.Model{Float64}()
2828
bridge = DummyBridge()
29-
attr = MOI.ConstraintPrimalStart()
30-
@test !MOI.supports(model, attr, typeof(bridge))
31-
@test_throws MOI.UnsupportedAttribute(attr) MOI.set(
32-
model,
33-
attr,
34-
bridge,
35-
1.0,
29+
@test !MOI.supports(model, MOI.ConstraintPrimalStart(), typeof(bridge))
30+
message = MOI.Bridges._attribute_error_message(
31+
MOI.ConstraintPrimalStart(),
32+
DummyBridge,
33+
"setting a value for",
3634
)
37-
attr = MOI.ConstraintFunction()
38-
err = MOI.SetAttributeNotAllowed(attr)
39-
@test_throws err MOI.set(model, attr, bridge, MOI.EqualTo(1.0))
35+
@test_throws(
36+
MOI.UnsupportedAttribute(MOI.ConstraintPrimalStart(), message),
37+
MOI.set(model, MOI.ConstraintPrimalStart(), bridge, 1.0),
38+
)
39+
message = MOI.Bridges._attribute_error_message(
40+
MOI.ConstraintSet(),
41+
DummyBridge,
42+
"setting a value for",
43+
)
44+
@test_throws(
45+
MOI.SetAttributeNotAllowed(MOI.ConstraintSet(), message),
46+
MOI.set(model, MOI.ConstraintSet(), bridge, MOI.EqualTo(1.0)),
47+
)
48+
return
4049
end
4150

4251
end # module

test/Bridges/bridge_optimizer.jl

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,17 @@ MOI.Utilities.@model(
218218
(MOI.VectorAffineFunction, MOI.VectorQuadraticFunction)
219219
)
220220

221-
function unsupported_constraint_attribute()
221+
struct AttributeNotAllowed <: MOI.AbstractConstraintAttribute end
222+
223+
function MOI.supports(
224+
::MOI.ModelLike,
225+
::AttributeNotAllowed,
226+
::Type{<:MOI.Bridges.Constraint.SplitIntervalBridge},
227+
)
228+
return true
229+
end
230+
231+
function test_unsupported_constraint_attribute()
222232
mock = MOI.Utilities.MockOptimizer(NoIntervalModel{Float64}())
223233
bridged_mock = MOI.Bridges.Constraint.LessToGreater{Float64}(
224234
MOI.Bridges.Constraint.SplitInterval{Float64}(mock),
@@ -231,22 +241,19 @@ function unsupported_constraint_attribute()
231241
MOI.LessThan{Float64},
232242
}
233243
attr = MOI.Test.UnknownConstraintAttribute()
234-
err = ArgumentError(
235-
"Bridge of type `$(bridge)` does not support accessing " *
236-
"the attribute `$attr`. If you encountered this error " *
237-
"unexpectedly, it probably means your model has been " *
238-
"reformulated using the bridge, and you are attempting to query " *
239-
"an attribute that we haven't implemented yet for this bridge. " *
240-
"Please open an issue at https://github.com/jump-dev/MathOptInterface.jl/issues/new " *
241-
"and provide a reproducible example explaining what you were " *
242-
"trying to do.",
243-
)
244+
message(action) = MOI.Bridges._attribute_error_message(attr, bridge, action)
244245
x = MOI.add_variable(bridged_mock)
245246
ci = MOI.add_constraint(bridged_mock, x, MOI.Interval(0.0, 1.0))
246247
@test !MOI.Bridges.is_bridged(bridged_mock, ci)
247248
@test MOI.Bridges.is_bridged(bridged_mock.model, ci)
248249
@test !MOI.supports(bridged_mock, attr, typeof(ci))
250+
err = ArgumentError(message("accessing"))
249251
@test_throws err MOI.get(bridged_mock, attr, ci)
252+
err = MOI.UnsupportedAttribute(attr, message("setting a value for"))
253+
@test_throws err MOI.set(bridged_mock, attr, ci, 1)
254+
attr = AttributeNotAllowed()
255+
err = MOI.SetAttributeNotAllowed(attr, message("setting a value for"))
256+
@test_throws err MOI.set(bridged_mock, attr, ci, 1)
250257
return
251258
end
252259

0 commit comments

Comments
 (0)