From 926d96aee749a4d4283d90331fe1b5ec67f1e193 Mon Sep 17 00:00:00 2001 From: Robert Parker Date: Sun, 2 Feb 2025 11:49:56 -0500 Subject: [PATCH 1/8] allow construction of CUID from another CUID --- pyomo/core/base/componentuid.py | 4 +++- pyomo/core/tests/unit/test_componentuid.py | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/pyomo/core/base/componentuid.py b/pyomo/core/base/componentuid.py index 2075aa197dc..fdcb7a899dd 100644 --- a/pyomo/core/base/componentuid.py +++ b/pyomo/core/base/componentuid.py @@ -12,6 +12,7 @@ import codecs import re import ply.lex +import copy from pyomo.common.collections import ComponentMap from pyomo.common.dependencies import pickle @@ -86,7 +87,8 @@ def __init__(self, component, cuid_buffer=None, context=None): self._cids = tuple(self._parse_cuid_v2(component)) except (OSError, IOError): self._cids = tuple(self._parse_cuid_v1(component)) - + elif isinstance(component, ComponentUID): + self._cids = copy.deepcopy(component._cids) elif type(component) is IndexedComponent_slice: self._cids = tuple( self._generate_cuid_from_slice(component, context=context) diff --git a/pyomo/core/tests/unit/test_componentuid.py b/pyomo/core/tests/unit/test_componentuid.py index 5808bedb7fd..e95c7ae731d 100644 --- a/pyomo/core/tests/unit/test_componentuid.py +++ b/pyomo/core/tests/unit/test_componentuid.py @@ -1248,6 +1248,23 @@ def test_cuid_from_slice_errors(self): ): cuid = ComponentUID(_slice) + def test_cuid_from_cuid(self): + def assert_equal(cuid1, cuid2): + self.assertEqual(cuid1, cuid2) + self.assertFalse(cuid1 is cuid2) + + cuid_str = ComponentUID("b.var[1]") + cuid_str_2 = ComponentUID(cuid_str) + assert_equal(cuid_str, cuid_str_2) + + cuid_comp = ComponentUID(self.m.b[1, 1].c) + cuid_comp_2 = ComponentUID(cuid_comp) + assert_equal(cuid_str, cuid_str_2) + + cuid_slice = ComponentUID(self.m.b[1, :].c) + cuid_slice_2 = ComponentUID(cuid_slice) + assert_equal(cuid_slice, cuid_slice_2) + if __name__ == "__main__": unittest.main() From 4640f64b28aa74b49e59668b06e347a60ff542ad Mon Sep 17 00:00:00 2001 From: Robert Parker Date: Sun, 2 Feb 2025 12:04:17 -0500 Subject: [PATCH 2/8] dont need to check for cuid in find_component --- pyomo/core/base/block.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pyomo/core/base/block.py b/pyomo/core/base/block.py index 656bf6008c4..47f398e5b60 100644 --- a/pyomo/core/base/block.py +++ b/pyomo/core/base/block.py @@ -921,11 +921,7 @@ def find_component(self, label_or_component): a matching component is not found, None is returned. """ - if type(label_or_component) is ComponentUID: - cuid = label_or_component - else: - cuid = ComponentUID(label_or_component) - return cuid.find_component_on(self) + return ComponentUID(label_or_component).find_component_on(self) @contextmanager def _declare_reserved_components(self): From e696783d0ca335b4bf78a3921c7591f19abcbce0 Mon Sep 17 00:00:00 2001 From: Robert Parker Date: Sun, 2 Feb 2025 12:06:06 -0500 Subject: [PATCH 3/8] dont need to check for cuid in get_indexed_cuid --- pyomo/contrib/mpc/data/get_cuid.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pyomo/contrib/mpc/data/get_cuid.py b/pyomo/contrib/mpc/data/get_cuid.py index ef0df7ea679..a6889551b3c 100644 --- a/pyomo/contrib/mpc/data/get_cuid.py +++ b/pyomo/contrib/mpc/data/get_cuid.py @@ -37,11 +37,8 @@ def get_indexed_cuid(var, sets=None, dereference=None, context=None): ComponentUID corresponding to the provided ``var`` and sets """ - # TODO: Does this function have a good name? # Should this function be generalized beyond a single indexing set? - if isinstance(var, ComponentUID): - return var - elif isinstance(var, (str, IndexedComponent_slice)): + if isinstance(var, (str, IndexedComponent_slice, ComponentUID)): # TODO: Raise error if string and context is None return ComponentUID(var, context=context) # At this point we are assuming var is a Pyomo Var or VarData object. From ae4e0d19434bb1dc2b19ff4bf8894bd7b02092a2 Mon Sep 17 00:00:00 2001 From: Robert Parker Date: Sun, 2 Feb 2025 12:17:02 -0500 Subject: [PATCH 4/8] error when CUID and context are provided --- pyomo/core/base/componentuid.py | 11 +++++++---- pyomo/core/tests/unit/test_componentuid.py | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pyomo/core/base/componentuid.py b/pyomo/core/base/componentuid.py index fdcb7a899dd..3c367b0aade 100644 --- a/pyomo/core/base/componentuid.py +++ b/pyomo/core/base/componentuid.py @@ -77,17 +77,20 @@ class ComponentUID(object): def __init__(self, component, cuid_buffer=None, context=None): # A CUID can be initialized from either a reference component or # the string representation. + def _context_err(_type): + raise ValueError( + f"Context is not allowed when initializing a ComponentUID from {_type}." + ) if isinstance(component, str): if context is not None: - raise ValueError( - "Context is not allowed when initializing a " - "ComponentUID object from a string type" - ) + _context_err(str) try: self._cids = tuple(self._parse_cuid_v2(component)) except (OSError, IOError): self._cids = tuple(self._parse_cuid_v1(component)) elif isinstance(component, ComponentUID): + if context is not None: + _context_err(ComponentUID) self._cids = copy.deepcopy(component._cids) elif type(component) is IndexedComponent_slice: self._cids = tuple( diff --git a/pyomo/core/tests/unit/test_componentuid.py b/pyomo/core/tests/unit/test_componentuid.py index e95c7ae731d..53474c848b6 100644 --- a/pyomo/core/tests/unit/test_componentuid.py +++ b/pyomo/core/tests/unit/test_componentuid.py @@ -83,8 +83,7 @@ def test_genFromComponent_context(self): ComponentUID(self.m.s, context=self.m.b[1, '2']) with self.assertRaisesRegex( ValueError, - "Context is not allowed when initializing a ComponentUID " - "object from a string type", + "Context is not allowed when initializing a ComponentUID from" ): ComponentUID("b[1,2].c.a[2]", context=self.m.b[1, '2']) @@ -1265,6 +1264,9 @@ def assert_equal(cuid1, cuid2): cuid_slice_2 = ComponentUID(cuid_slice) assert_equal(cuid_slice, cuid_slice_2) + with self.assertRaisesRegex(ValueError, "Context is not allowed"): + ComponentUID(cuid_comp, context=self.m.b[1, 1]) + if __name__ == "__main__": unittest.main() From 2357c03160be12e6a49e17d35bf04e486784cacf Mon Sep 17 00:00:00 2001 From: Robert Parker Date: Sun, 2 Feb 2025 12:24:46 -0500 Subject: [PATCH 5/8] black --- pyomo/core/base/componentuid.py | 1 + pyomo/core/tests/unit/test_componentuid.py | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pyomo/core/base/componentuid.py b/pyomo/core/base/componentuid.py index 3c367b0aade..4d3a2179a99 100644 --- a/pyomo/core/base/componentuid.py +++ b/pyomo/core/base/componentuid.py @@ -81,6 +81,7 @@ def _context_err(_type): raise ValueError( f"Context is not allowed when initializing a ComponentUID from {_type}." ) + if isinstance(component, str): if context is not None: _context_err(str) diff --git a/pyomo/core/tests/unit/test_componentuid.py b/pyomo/core/tests/unit/test_componentuid.py index 53474c848b6..1250a58b240 100644 --- a/pyomo/core/tests/unit/test_componentuid.py +++ b/pyomo/core/tests/unit/test_componentuid.py @@ -81,10 +81,7 @@ def test_genFromComponent_context(self): ValueError, r"Context 'b\[1,'2'\]' does not apply to component 's'" ): ComponentUID(self.m.s, context=self.m.b[1, '2']) - with self.assertRaisesRegex( - ValueError, - "Context is not allowed when initializing a ComponentUID from" - ): + with self.assertRaisesRegex(ValueError, "Context is not allowed"): ComponentUID("b[1,2].c.a[2]", context=self.m.b[1, '2']) def test_parseFromString(self): From c23320f4cfe446f45aa44ee0ba58595bc3fe22b9 Mon Sep 17 00:00:00 2001 From: Robert Parker Date: Mon, 3 Feb 2025 22:12:38 -0500 Subject: [PATCH 6/8] address review --- pyomo/core/base/componentuid.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/pyomo/core/base/componentuid.py b/pyomo/core/base/componentuid.py index 4d3a2179a99..18e53ae9675 100644 --- a/pyomo/core/base/componentuid.py +++ b/pyomo/core/base/componentuid.py @@ -12,7 +12,6 @@ import codecs import re import ply.lex -import copy from pyomo.common.collections import ComponentMap from pyomo.common.dependencies import pickle @@ -74,25 +73,25 @@ class ComponentUID(object): str: lambda x: '$' + str(x), } + def _context_err(self, _type): + raise ValueError( + f"Context is not allowed when initializing a ComponentUID from {_type}." + ) + def __init__(self, component, cuid_buffer=None, context=None): # A CUID can be initialized from either a reference component or # the string representation. - def _context_err(_type): - raise ValueError( - f"Context is not allowed when initializing a ComponentUID from {_type}." - ) - if isinstance(component, str): if context is not None: - _context_err(str) + self._context_err(str) try: self._cids = tuple(self._parse_cuid_v2(component)) except (OSError, IOError): self._cids = tuple(self._parse_cuid_v1(component)) - elif isinstance(component, ComponentUID): + elif type(component) is ComponentUID): if context is not None: - _context_err(ComponentUID) - self._cids = copy.deepcopy(component._cids) + self._context_err(ComponentUID) + self._cids = component._cids elif type(component) is IndexedComponent_slice: self._cids = tuple( self._generate_cuid_from_slice(component, context=context) From 59265103992883cc02c1c50dbf64c47f94662a87 Mon Sep 17 00:00:00 2001 From: Robert Parker Date: Mon, 3 Feb 2025 22:15:28 -0500 Subject: [PATCH 7/8] fix syntax error --- pyomo/core/base/componentuid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyomo/core/base/componentuid.py b/pyomo/core/base/componentuid.py index 18e53ae9675..741b98a0019 100644 --- a/pyomo/core/base/componentuid.py +++ b/pyomo/core/base/componentuid.py @@ -88,7 +88,7 @@ def __init__(self, component, cuid_buffer=None, context=None): self._cids = tuple(self._parse_cuid_v2(component)) except (OSError, IOError): self._cids = tuple(self._parse_cuid_v1(component)) - elif type(component) is ComponentUID): + elif type(component) is ComponentUID: if context is not None: self._context_err(ComponentUID) self._cids = component._cids From 682ebbfc8a882778b8c6482c906a693345d4f80c Mon Sep 17 00:00:00 2001 From: Robert Parker Date: Tue, 4 Feb 2025 11:13:29 -0500 Subject: [PATCH 8/8] function in module scope --- pyomo/core/base/componentuid.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pyomo/core/base/componentuid.py b/pyomo/core/base/componentuid.py index 741b98a0019..a0009b1e1b7 100644 --- a/pyomo/core/base/componentuid.py +++ b/pyomo/core/base/componentuid.py @@ -43,6 +43,12 @@ def _index_repr(x): return __index_repr(x, _pickle) +def _context_err(_type): + raise ValueError( + f"Context is not allowed when initializing a ComponentUID from {_type}." + ) + + class ComponentUID(object): """ A Component unique identifier @@ -73,24 +79,19 @@ class ComponentUID(object): str: lambda x: '$' + str(x), } - def _context_err(self, _type): - raise ValueError( - f"Context is not allowed when initializing a ComponentUID from {_type}." - ) - def __init__(self, component, cuid_buffer=None, context=None): # A CUID can be initialized from either a reference component or # the string representation. if isinstance(component, str): if context is not None: - self._context_err(str) + _context_err(str) try: self._cids = tuple(self._parse_cuid_v2(component)) except (OSError, IOError): self._cids = tuple(self._parse_cuid_v1(component)) elif type(component) is ComponentUID: if context is not None: - self._context_err(ComponentUID) + _context_err(ComponentUID) self._cids = component._cids elif type(component) is IndexedComponent_slice: self._cids = tuple(