From 2c3eddc6c9ffeff2dcd836f98395d28d4e5bbd5d Mon Sep 17 00:00:00 2001 From: Fumito Hamamura Date: Sun, 14 Jul 2024 14:57:42 +0900 Subject: [PATCH 1/2] ENH: Add _name as alies fro name --- modelx/core/base.py | 2 ++ modelx/export/_mx_sys.py | 1 + modelx/export/exporter.py | 2 ++ 3 files changed, 5 insertions(+) diff --git a/modelx/core/base.py b/modelx/core/base.py index 1aeeb08..8cd5519 100644 --- a/modelx/core/base.py +++ b/modelx/core/base.py @@ -359,6 +359,8 @@ def name(self): """Name of the object.""" return self._impl.name + _name = name + @property def fullname(self): """Dotted name of the object. diff --git a/modelx/export/_mx_sys.py b/modelx/export/_mx_sys.py index 7910891..9c36dbd 100644 --- a/modelx/export/_mx_sys.py +++ b/modelx/export/_mx_sys.py @@ -19,6 +19,7 @@ class BaseParent(BaseMxObject): _mx_spaces: Dict[str, 'BaseSpace'] _parent: 'BaseParent' _model: 'BaseModel' + _name: str def _mx_walk(self, skip_self: bool = False): """Generator yielding spaces in breadth-first order""" diff --git a/modelx/export/exporter.py b/modelx/export/exporter.py index e70d022..a7dceee 100644 --- a/modelx/export/exporter.py +++ b/modelx/export/exporter.py @@ -297,6 +297,7 @@ def __init__(self): # modelx variables self._parent = None self._model = self + self._name = "{name}" {space_assigns} {space_dict} @@ -347,6 +348,7 @@ def __init__(self, parent): self._space = self self._parent = parent self._model = parent._model + self._name = "{name}" {space_assigns} {space_dict} From ad47dfc5593373f4a6a92387541117c042554324 Mon Sep 17 00:00:00 2001 From: Fumito Hamamura Date: Sun, 14 Jul 2024 20:37:57 +0900 Subject: [PATCH 2/2] ENH: Add _cells and _name in exported spaces --- modelx/core/space.py | 2 ++ modelx/export/_mx_sys.py | 16 ++++++++++++++ modelx/export/exporter.py | 19 +++++++++++++++- modelx/tests/export/test_export.py | 34 +++++++++++++++++++++++++++++ modelx/tests/export/test_lifelib.py | 29 ++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 1 deletion(-) diff --git a/modelx/core/space.py b/modelx/core/space.py index 8ce54f8..05448a2 100644 --- a/modelx/core/space.py +++ b/modelx/core/space.py @@ -365,6 +365,8 @@ def cells(self): """A mapping of cells names to the cells objects in the space.""" return self._impl.cells.interfaces + _cells = cells + @property def spaces(self): """A mapping associating names to named spaces.""" diff --git a/modelx/export/_mx_sys.py b/modelx/export/_mx_sys.py index 9c36dbd..72168a8 100644 --- a/modelx/export/_mx_sys.py +++ b/modelx/export/_mx_sys.py @@ -68,6 +68,22 @@ def _mx_load_io(self): class BaseSpace(BaseParent): + # Class variable + _mx_cells_names: list + + # Instance variables + _mx_is_cells_set: bool + _mx_cells: dict + + @property + def _cells(self): + if not self._mx_is_cells_set: + for name in self._mx_cells_names: + self._mx_cells[name] = getattr(self, name) + self._mx_is_cells_set = True + + return self._mx_cells + def _mx_is_in(self, parent: BaseParent): p = self diff --git a/modelx/export/exporter.py b/modelx/export/exporter.py index a7dceee..e406f3f 100644 --- a/modelx/export/exporter.py +++ b/modelx/export/exporter.py @@ -342,6 +342,8 @@ class SpaceTranslator(ParentTranslator): class_template = textwrap.dedent("""\ class _c_{name}(_mx_sys.BaseSpace): + {cells_names_assign} + def __init__(self, parent): # modelx variables @@ -352,6 +354,8 @@ def __init__(self, parent): {space_assigns} {space_dict} + self._mx_cells = {{}} # Populated on calling self._cells + self._mx_is_cells_set = False {itemspace_dict} self._mx_roots = [] # Dynamic Space only @@ -532,6 +536,7 @@ def _get_class_def(self, space: BaseSpace): return self.class_template.format( name=space.name, + cells_names_assign=textwrap.indent(self.cells_names_assign(space), ' ' * 4), space_assigns=textwrap.indent(self.space_assigns(space), ' ' * 8), space_dict=textwrap.indent(self.space_dict(space), ' ' * 8), itemspace_dict=textwrap.indent(itemspace_dict, ' ' * 8), @@ -571,4 +576,16 @@ def param_assigns(self, params, copy=False): else: result.append('pass') - return "\n".join(result) \ No newline at end of file + return "\n".join(result) + + def cells_names_assign(self, space): + str_elm = [] + if space.cells: + str_elm.append("\n") + for name in space.cells: + str_elm.append("'" + name + "'") + str_elm.append(",\n") + template = textwrap.dedent("""\ + _mx_cells_names = [{names}] + """) + return template.format(names=textwrap.indent(''.join(str_elm), ' ' * 4)) \ No newline at end of file diff --git a/modelx/tests/export/test_export.py b/modelx/tests/export/test_export.py index 5073fee..8f8439e 100644 --- a/modelx/tests/export/test_export.py +++ b/modelx/tests/export/test_export.py @@ -290,6 +290,40 @@ def BEL_LAPSE(): for i in range(1, 5): nomx.RA[i].BEL_LAPSE() == 120 + finally: + sys.path.pop(0) + m.close() + + +def test_space_properties(tmp_path_factory): + + m = mx.new_model() + s1 = m.new_space("Space1") + s2 = s1.new_space("Space2") + + @mx.defcells(space=s1) + def get_parent(): + return _space._parent + + @mx.defcells(space=s2) + def get_parent(): + return _space._parent + + @mx.defcells(space=s1) + def get_name(): + return _space._name + + nomx_path = tmp_path_factory.mktemp('model') + m.export(nomx_path / 'TestSpaceProperties_nomx') + + try: + sys.path.insert(0, str(nomx_path)) + from TestSpaceProperties_nomx import mx_model as nomx + + assert nomx.Space1.get_parent() is nomx + assert nomx.Space1.Space2.get_parent() is nomx.Space1 + assert nomx.Space1.get_name() == "Space1" + finally: sys.path.pop(0) m.close() \ No newline at end of file diff --git a/modelx/tests/export/test_lifelib.py b/modelx/tests/export/test_lifelib.py index e5dfc36..3608b72 100644 --- a/modelx/tests/export/test_lifelib.py +++ b/modelx/tests/export/test_lifelib.py @@ -54,6 +54,35 @@ def test_basiclife_and_savings(basiclife_and_savings): ) +def test_appliedlife(tmp_path_factory): + import lifelib + library, name = 'appliedlife', 'IntegratedLife' + + work_dir = tmp_path_factory.mktemp('tmp') / library + lifelib.create(library, work_dir) + + model = mx.read_model(work_dir / name) + model.export(work_dir / (name + '_nomx')) + + try: + sys.path.insert(0, str(work_dir)) + nomx = importlib.import_module((name + '_nomx')).mx_model + + pd.testing.assert_frame_equal( + model.Run[1].GMXB.result_pv(), + nomx.Run[1].GMXB.result_pv() + ) + + pd.testing.assert_frame_equal( + model.Run[1].GMXB.result_sample(), + nomx.Run[1].GMXB.result_sample() + ) + + finally: + sys.path.pop(0) + model.close() + + def test_assets(tmp_path_factory): import lifelib library, name, arg = 'assets', 'BasicBonds', None