From 80dcf7cc0e9266a702873194dfae961f97a0c3cb Mon Sep 17 00:00:00 2001 From: David Hadka Date: Tue, 10 Sep 2024 20:43:52 +0000 Subject: [PATCH] Add test for decorators --- rhodium/decorators.py | 20 +++++++--------- rhodium/model.py | 9 ++++--- rhodium/test/decorators_test.py | 42 +++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 rhodium/test/decorators_test.py diff --git a/rhodium/decorators.py b/rhodium/decorators.py index bd78d2b..4903008 100644 --- a/rhodium/decorators.py +++ b/rhodium/decorators.py @@ -17,17 +17,13 @@ # along with Rhodium. If not, see . import random import inspect +from abc import ABCMeta from .model import Constraint, Lever, Model, Parameter, Response, \ Uncertainty, CategoricalLever, IntegerLever, PermutationLever, \ SubsetLever, RealLever, UniformUncertainty, NormalUncertainty, \ - LogNormalUncertainty + LogNormalUncertainty, Direction -MINIMIZE = Response.MINIMIZE -MAXIMIZE = Response.MAXIMIZE -INFO = Response.INFO -IGNORE = Response.IGNORE - -class UnnamedObject: +class UnnamedObject(metaclass=ABCMeta): def __init__(self, constructor, *args, **kwargs): self.constructor = constructor @@ -89,22 +85,22 @@ def __new__(cls, *args, **kwargs): class Minimize(Response): def __init__(self, name, **kwargs): - super().__init__(name, type=Response.MINIMIZE, **kwargs) + super().__init__(name, direction=Direction.MINIMIZE, **kwargs) class Maximize(Response): def __init__(self, name, **kwargs): - super().__init__(name, type=Response.MAXIMIZE, **kwargs) + super().__init__(name, direction=Direction.MAXIMIZE, **kwargs) class Info(Response): def __init__(self, name, **kwargs): - super().__init__(name, type=Response.INFO, **kwargs) + super().__init__(name, direction=Direction.INFO, **kwargs) class Ignore(Response): - def __init__(self, **kwargs): - super().__init__("Ignored" + str(random.randint()), type=Response.IGNORE, **kwargs) + def __init__(self, name=None, **kwargs): + super().__init__("Ignored" + str(random.randint()) if name is None else name, direction=Direction.IGNORE, **kwargs) class CallableModel(Model): diff --git a/rhodium/model.py b/rhodium/model.py index db0379c..3e57abf 100644 --- a/rhodium/model.py +++ b/rhodium/model.py @@ -67,11 +67,10 @@ class Direction(Enum): class Response(NamedObject): """Defines a model response (i.e., output). - Defines a model response (i.e., output) and its type. The type can be - MINIMIZE, MAXIMIZE, or INFO. If MINIMIZE or MAXIMIZE, then the response - may be used during optimization. If INFO, the default, the response is - purely for informative purposes (e.g., for generating plots) but does not - participate in optimization. + Defines a model response (i.e., output) and its direction. If MINIMIZE or + MAXIMIZE, then the response may be used during optimization. If INFO, the + default, the response is purely for informative purposes (e.g., for + generating plots) but does not participate in optimization. """ # These constants are deprecated. Use the Direction enum instead. diff --git a/rhodium/test/decorators_test.py b/rhodium/test/decorators_test.py new file mode 100644 index 0000000..e7f6c21 --- /dev/null +++ b/rhodium/test/decorators_test.py @@ -0,0 +1,42 @@ +# Copyright 2015-2024 David Hadka +# +# This file is part of Rhodium, a Python module for robust decision +# making and exploratory modeling. +# +# Rhodium is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Rhodium is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Rhodium. If not, see . +import unittest +from ..model import Direction +from ..decorators import Minimize, Maximize, Info, Ignore + +class TestResponses(unittest.TestCase): + + def testMinimize(self): + r = Minimize("foo") + self.assertEqual("foo", r.name) + self.assertEqual(Direction.MINIMIZE, r.direction) + + def testMaximize(self): + r = Maximize("foo") + self.assertEqual("foo", r.name) + self.assertEqual(Direction.MAXIMIZE, r.direction) + + def testInfo(self): + r = Info("foo") + self.assertEqual("foo", r.name) + self.assertEqual(Direction.INFO, r.direction) + + def testIgnore(self): + r = Ignore("foo") + self.assertEqual("foo", r.name) + self.assertEqual(Direction.IGNORE, r.direction)