Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type check all exception arguments in component __call__ implementations #3538

Merged
merged 27 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d0ff0f1
Param raises a ValueError when 'exception' arg is not a bool
emma58 Mar 24, 2025
a6b1cbb
black
emma58 Mar 24, 2025
aa38102
more black
emma58 Mar 24, 2025
3216fea
Moving the implementation of the type checker for the exception arg t…
emma58 Mar 25, 2025
c47b8dd
Type-checking exception arg in Expression
emma58 Mar 25, 2025
1efee8d
Type checking exception arg for Objective
emma58 Mar 25, 2025
bb3a1c8
Type checking exception arg for units
emma58 Mar 25, 2025
3225949
Type checking exception arg for Var
emma58 Mar 25, 2025
4ec511e
black
emma58 Mar 25, 2025
4f54c06
Type checking exception arg in BooleanVar
emma58 Mar 25, 2025
b211822
Type checking exception arg in Constraint
emma58 Mar 25, 2025
3ee7810
Type checking exception arg for LogicalConstraint
emma58 Mar 25, 2025
472ccfb
Type checking exception arg for matrix constraint
emma58 Mar 25, 2025
707fe6a
Moving the exception arg type check implementation to expr_common for…
emma58 Mar 25, 2025
4999f5f
Type checking exception arg in boolean value
emma58 Mar 25, 2025
4dad55e
Type checking exception arg in numvalue
emma58 Mar 25, 2025
9c2a87c
Template expr exception flag will be checked by ExpressionBase __call…
emma58 Mar 25, 2025
f572ba3
black
emma58 Mar 25, 2025
5698c14
Type checking exception arg in kernel/expression
emma58 Mar 25, 2025
c10a3d7
Type checking exception in kernel matrix constraint
emma58 Mar 25, 2025
ae6ea8c
Type checking exception arg in conic
emma58 Mar 25, 2025
264c714
Type checking exception arg in kernel parameter
emma58 Mar 25, 2025
defb293
type checking exception arg for kernel variable
emma58 Mar 25, 2025
3588dc1
type checking exception arg for kernel constraint
emma58 Mar 25, 2025
12c81fa
black
emma58 Mar 25, 2025
9fa799a
Type checking exception arg in beta/matrix
emma58 Mar 25, 2025
70cc92f
Merge branch 'main' into params-complain-more
jsiirola Mar 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pyomo/core/base/boolean_var.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from pyomo.core.staleflag import StaleFlagManager
from pyomo.core.expr.boolean_value import BooleanValue
from pyomo.core.expr import GetItemExpression
from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.numvalue import value
from pyomo.core.base.component import ComponentData, ModelComponentFactory
from pyomo.core.base.global_set import UnindexedComponent_index
Expand Down Expand Up @@ -155,8 +156,9 @@ def set_value(self, val, skip_validation=False):
def clear(self):
self.value = None

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Compute the value of this variable."""
exception = _type_check_exception_arg(self, exception)
return self.value

@property
Expand Down
4 changes: 3 additions & 1 deletion pyomo/core/base/constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
InequalityExpression,
RangedExpression,
)
from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.template_expr import templatize_constraint
from pyomo.core.base.component import ActiveComponentData, ModelComponentFactory
from pyomo.core.base.global_set import UnindexedComponent_index
Expand Down Expand Up @@ -168,8 +169,9 @@ def __init__(self, expr=None, component=None):
if expr is not None:
self.set_value(expr)

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Compute the value of the body of this constraint."""
exception = _type_check_exception_arg(self, exception)
body = self.to_bounded_expression()[1]
if body.__class__ not in native_numeric_types:
body = value(self.body, exception=exception)
Expand Down
7 changes: 5 additions & 2 deletions pyomo/core/base/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
)

import pyomo.core.expr as EXPR
from pyomo.core.expr.expr_common import _type_check_exception_arg
import pyomo.core.expr.numeric_expr as numeric_expr
from pyomo.core.base.component import ComponentData, ModelComponentFactory
from pyomo.core.base.global_set import UnindexedComponent_index
Expand All @@ -50,8 +51,9 @@ class NamedExpressionData(numeric_expr.NumericValue):
PRECEDENCE = 0
ASSOCIATIVITY = EXPR.OperatorAssociativity.NON_ASSOCIATIVE

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Compute the value of this expression."""
exception = _type_check_exception_arg(self, exception)
(arg,) = self.args
if arg.__class__ in native_types:
# Note: native_types includes NoneType
Expand Down Expand Up @@ -396,8 +398,9 @@ def __init__(self, *args, **kwds):
# construction
#

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Return expression on this expression."""
exception = _type_check_exception_arg(self, exception)
if self._constructed:
return super().__call__(exception)
raise ValueError(
Expand Down
4 changes: 3 additions & 1 deletion pyomo/core/base/logical_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from pyomo.common.modeling import NOTSET
from pyomo.common.timing import ConstructionTimer

from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.boolean_value import as_boolean, BooleanConstant
from pyomo.core.expr.numvalue import native_types, native_logical_types
from pyomo.core.base.component import ActiveComponentData, ModelComponentFactory
Expand Down Expand Up @@ -84,8 +85,9 @@
if expr is not None:
self.set_value(expr)

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Compute the value of the body of this logical constraint."""
exception = _type_check_exception_arg(self, exception)

Check warning on line 90 in pyomo/core/base/logical_constraint.py

View check run for this annotation

Codecov / codecov/patch

pyomo/core/base/logical_constraint.py#L90

Added line #L90 was not covered by tests
if self.body is None:
return None
return self.body(exception=exception)
Expand Down
5 changes: 4 additions & 1 deletion pyomo/core/base/matrix_constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@

from pyomo.common.gc_manager import PauseGC
from pyomo.common.log import is_debug_set
from pyomo.common.modeling import NOTSET
from pyomo.core.base.set_types import Any
from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.numvalue import value
from pyomo.core.expr.numeric_expr import LinearExpression
from pyomo.core.base.component import ModelComponentFactory
Expand Down Expand Up @@ -130,8 +132,9 @@ def __getstate__(self):
# possible
#

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Compute the value of the body of this constraint."""
exception = _type_check_exception_arg(self, exception)
comp = self.parent_component()
index = self._index
data = comp._A_data
Expand Down
4 changes: 3 additions & 1 deletion pyomo/core/base/objective.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from pyomo.common.formatting import tabular_writer
from pyomo.common.timing import ConstructionTimer

from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.numvalue import value
from pyomo.core.expr.template_expr import templatize_rule
from pyomo.core.base.component import ActiveComponentData, ModelComponentFactory
Expand Down Expand Up @@ -418,7 +419,8 @@ def __init__(self, *args, **kwd):
# construction
#

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
exception = _type_check_exception_arg(self, exception)
if self._constructed:
if len(self._data) == 0:
raise ValueError(
Expand Down
16 changes: 7 additions & 9 deletions pyomo/core/base/param.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from pyomo.common.modeling import NOTSET
from pyomo.common.numeric_types import native_types, value as expr_value
from pyomo.common.timing import ConstructionTimer
from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.numvalue import NumericValue
from pyomo.core.base.component import ComponentData, ModelComponentFactory
from pyomo.core.base.global_set import UnindexedComponent_index
Expand Down Expand Up @@ -201,10 +202,12 @@ def set_value(self, value, idx=NOTSET):
self._value = old_value
raise

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""
Return the value of this object.
"""
exception = _type_check_exception_arg(self, exception)

if self._value is Param.NoValue:
if exception:
raise ValueError(
Expand Down Expand Up @@ -929,10 +932,12 @@ def __init__(self, *args, **kwds):
# up both the Component and Data base classes.
#

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""
Return the value of this parameter.
"""
exception = _type_check_exception_arg(self, exception)

if self._constructed:
if not self._data:
if self._mutable:
Expand Down Expand Up @@ -976,13 +981,6 @@ class SimpleParam(metaclass=RenamedClass):


class IndexedParam(Param):
def __call__(self, exception=True):
"""Compute the value of the parameter"""
if exception:
raise TypeError(
'Cannot compute the value of an indexed Param (%s)' % (self.name,)
)

# Because IndexedParam can use a non-standard data store (i.e., the
# values in the _data dict may not be ComponentData objects), we
# need to override the normal scheme for pre-allocating
Expand Down
4 changes: 3 additions & 1 deletion pyomo/core/base/units_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@

from pyomo.common.dependencies import pint as pint_module, pint_available
from pyomo.common.modeling import NOTSET
from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.numvalue import (
NumericValue,
nonpyomo_leaf_types,
Expand Down Expand Up @@ -384,14 +385,15 @@ def to_string(self, verbose=None, labeler=None, smap=None, compute_values=False)
else:
return _str

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Unit is treated as a constant value, and this method always returns 1.0

Returns
-------
: float
Returns 1.0
"""
_type_check_exception_arg(self, exception)
return 1.0

@property
Expand Down
4 changes: 3 additions & 1 deletion pyomo/core/base/var.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from pyomo.core.staleflag import StaleFlagManager
from pyomo.core.expr import GetItemExpression
from pyomo.core.expr.numeric_expr import NPV_MaxExpression, NPV_MinExpression
from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.numvalue import (
NumericValue,
value,
Expand Down Expand Up @@ -197,8 +198,9 @@ def value(self):
def value(self, val):
self.set_value(val)

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Compute the value of this variable."""
exception = _type_check_exception_arg(self, exception)
return self._value

@property
Expand Down
6 changes: 4 additions & 2 deletions pyomo/core/expr/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

from pyomo.common.dependencies import attempt_import
from pyomo.common.numeric_types import native_types
from pyomo.common.modeling import NOTSET
from pyomo.core.pyomoobject import PyomoObject
from pyomo.core.expr.expr_common import OperatorAssociativity
from pyomo.core.expr.expr_common import OperatorAssociativity, _type_check_exception_arg

visitor, _ = attempt_import('pyomo.core.expr.visitor')

Expand Down Expand Up @@ -100,7 +101,7 @@ def args(self):
f"Derived expression ({self.__class__}) failed to implement args()"
)

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Evaluate the value of the expression tree.

Parameters
Expand All @@ -115,6 +116,7 @@ def __call__(self, exception=True):
The value of the expression or :const:`None`.

"""
exception = _type_check_exception_arg(self, exception)
return visitor.evaluate_expression(self, exception)

def __str__(self):
Expand Down
5 changes: 4 additions & 1 deletion pyomo/core/expr/boolean_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import logging

from pyomo.common.deprecation import deprecated
from pyomo.common.modeling import NOTSET
from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.expr.numvalue import native_types, native_logical_types
from pyomo.core.expr.expr_common import _and, _or, _equiv, _inv, _xor, _impl
from pyomo.core.pyomoobject import PyomoObject
Expand Down Expand Up @@ -296,8 +298,9 @@ def __nonzero__(self):
def __bool__(self):
return self.value

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Return the constant value"""
exception = _type_check_exception_arg(self, exception)
return self.value

def pprint(self, ostream=None, verbose=False):
Expand Down
13 changes: 13 additions & 0 deletions pyomo/core/expr/expr_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from pyomo.common import enums
from pyomo.common.deprecation import deprecated
from pyomo.common.modeling import NOTSET

TO_STRING_VERBOSE = False

Expand Down Expand Up @@ -108,3 +109,15 @@ def __init__(self):
def count(self):
"""A property that returns the clone count value."""
return clone_counter._count


def _type_check_exception_arg(cls, exception):
if exception is NOTSET:
return True
elif type(exception) is not bool:
raise ValueError(
f"{cls.ctype.__name__} '{cls.name}' was called with a non-bool "
f"argument for 'exception': {exception}"
)
else:
return exception
9 changes: 6 additions & 3 deletions pyomo/core/expr/numvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
deprecation_warning,
relocated_module_attribute,
)
from pyomo.core.expr.expr_common import ExpressionType
from pyomo.common.modeling import NOTSET
from pyomo.core.expr.expr_common import ExpressionType, _type_check_exception_arg
from pyomo.core.expr.numeric_expr import NumericValue

# TODO: update Pyomo to import these objects from common.numeric_types
Expand Down Expand Up @@ -113,7 +114,8 @@
def __repr__(self):
return repr(self.value)

def __call__(self, exception=None):
def __call__(self, exception=NOTSET):
exception = _type_check_exception_arg(self, exception)

Check warning on line 118 in pyomo/core/expr/numvalue.py

View check run for this annotation

Codecov / codecov/patch

pyomo/core/expr/numvalue.py#L118

Added line #L118 was not covered by tests
return self.value

def is_constant(self):
Expand Down Expand Up @@ -422,8 +424,9 @@
def __str__(self):
return str(self.value)

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Return the constant value"""
exception = _type_check_exception_arg(self, exception)
return self.value

def pprint(self, ostream=None, verbose=False):
Expand Down
5 changes: 5 additions & 0 deletions pyomo/core/expr/template_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ def __call__(self, *args, **kwargs):
#
# TODO: deprecate (then remove) evaluating expressions by
# "calling" them.
#
# [ESJ 3/25/25]: Note that since this always calls the ExpressionBase
# implementation of __call__ if 'exception' is specified, we need not
# check the type of the exception arg here--it will get checked in the
# base class.
try:
if not args:
if not kwargs:
Expand Down
5 changes: 4 additions & 1 deletion pyomo/core/kernel/conic.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
# ___________________________________________________________________________
"""Various conic constraint implementations."""

from pyomo.common.modeling import NOTSET
from pyomo.core.expr.numvalue import is_numeric_data
from pyomo.core.expr import value, exp
from pyomo.core.expr.expr_common import _type_check_exception_arg
from pyomo.core.kernel.block import block
from pyomo.core.kernel.variable import IVariable, variable, variable_tuple
from pyomo.core.kernel.constraint import (
Expand Down Expand Up @@ -133,7 +135,8 @@ def equality(self):
# to avoid building the body expression, if possible
#

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
exception = _type_check_exception_arg(self, exception)
try:
# we wrap the result with value(...) as the
# alpha term used by some of the constraints
Expand Down
9 changes: 6 additions & 3 deletions pyomo/core/kernel/constraint.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________

from pyomo.common.modeling import NOTSET
from pyomo.core.expr.numvalue import (
ZeroConstant,
as_numeric,
is_potentially_variable,
is_numeric_data,
value,
)
from pyomo.core.expr.expr_common import ExpressionType
from pyomo.core.expr.expr_common import ExpressionType, _type_check_exception_arg
from pyomo.core.expr.relational_expr import (
EqualityExpression,
RangedExpression,
Expand Down Expand Up @@ -74,8 +75,9 @@ class IConstraint(ICategorizedObject):
# Interface
#

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
"""Compute the value of the body of this constraint."""
exception = _type_check_exception_arg(self, exception)
if exception and (self.body is None):
raise ValueError("constraint body is None")
elif self.body is None:
Expand Down Expand Up @@ -798,7 +800,8 @@ def terms(self, terms):
# to avoid building the body expression
#

def __call__(self, exception=True):
def __call__(self, exception=NOTSET):
exception = _type_check_exception_arg(self, exception)
try:
return sum(
value(c, exception=exception) * v(exception=exception)
Expand Down
Loading
Loading