From 1bb685dcb38f2175c5ada3ce1c1fc0dd965bf288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 28 Sep 2023 14:02:02 +0200 Subject: [PATCH 1/9] Provide API to add Flows between existing Nodes --- src/oemof/network/network/nodes.py | 51 +++++++++++++++++++----------- tests/test_energy_system.py | 17 ++++++++++ 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/oemof/network/network/nodes.py b/src/oemof/network/network/nodes.py index eb017a1..fbbbace 100644 --- a/src/oemof/network/network/nodes.py +++ b/src/oemof/network/network/nodes.py @@ -15,35 +15,48 @@ from .entity import Entity +def _convert_to_dict(arg): + if type(arg) is dict: + return arg + else: + return dict.fromkeys(arg) + +_msg = "{} {!r} of {!r} not an instance of Node but of {}." + class Node(Entity): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._in_edges = set() - msg = "{} {!r} of {!r} not an instance of Node but of {}." - - for i in kwargs.get("inputs", {}): + inputs = kwargs.get("inputs", {}) + outputs = kwargs.get("outputs", {}) + self.add_inputs(inputs) + self.add_outputs(outputs) + + def add_inputs(self, inputs): + input_dict = _convert_to_dict(inputs) + for i, e in input_dict.items(): if not isinstance(i, Node): - raise ValueError(msg.format("Input", i, self, type(i))) + raise ValueError(_msg.format("Input", i, self, type(i))) self._in_edges.add(i) - try: - flow = kwargs["inputs"].get(i) - except AttributeError: - flow = None - edge = Edge.from_object(flow) + + edge = Edge.from_object(e) edge.input = i edge.output = self - for o in kwargs.get("outputs", {}): - if not isinstance(o, Node): - raise ValueError(msg.format("Output", o, self, type(o))) - try: - flow = kwargs["outputs"].get(o) - except AttributeError: - flow = None - edge = Edge.from_object(flow) - edge.input = self - edge.output = o + + def add_outputs(self, outputs): + output_dict = _convert_to_dict(outputs) + for o, f in output_dict.items(): + if isinstance(o, Node): + o.add_inputs({self: f}) + else: + raise ValueError(_msg.format("Input", o, self, type(o))) + + + + + class Bus(Node): diff --git a/tests/test_energy_system.py b/tests/test_energy_system.py index 9af475e..7d166b4 100644 --- a/tests/test_energy_system.py +++ b/tests/test_energy_system.py @@ -42,6 +42,23 @@ def test_add_nodes(self): assert node2 in self.es.nodes assert (node1, node2) in self.es.flows().keys() + def test_add_flow(self): + assert not self.es.nodes + + node1 = Node(label="node1") + node2 = Node(label="node2") + + self.es.add(node1, node2) + + node2.add_inputs({node1: Edge()}) + + assert (node1, node2) in self.es.flows().keys() + assert (node2, node1) not in self.es.flows().keys() + + node2.add_outputs({node1: Edge()}) + assert (node2, node1) in self.es.flows().keys() + + def test_that_node_additions_are_signalled(self): """ When a node gets `add`ed, a corresponding signal should be emitted. From 6ca49bbbd4e818d0fc6f46a6efaa5599211f7a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 28 Sep 2023 14:09:30 +0200 Subject: [PATCH 2/9] Adhere to Black --- src/oemof/network/network/nodes.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/oemof/network/network/nodes.py b/src/oemof/network/network/nodes.py index fbbbace..79d51e9 100644 --- a/src/oemof/network/network/nodes.py +++ b/src/oemof/network/network/nodes.py @@ -16,13 +16,15 @@ def _convert_to_dict(arg): - if type(arg) is dict: - return arg - else: - return dict.fromkeys(arg) + if type(arg) is dict: + return arg + else: + return dict.fromkeys(arg) + _msg = "{} {!r} of {!r} not an instance of Node but of {}." + class Node(Entity): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -33,14 +35,14 @@ def __init__(self, *args, **kwargs): outputs = kwargs.get("outputs", {}) self.add_inputs(inputs) self.add_outputs(outputs) - + def add_inputs(self, inputs): input_dict = _convert_to_dict(inputs) for i, e in input_dict.items(): if not isinstance(i, Node): raise ValueError(_msg.format("Input", i, self, type(i))) self._in_edges.add(i) - + edge = Edge.from_object(e) edge.input = i edge.output = self @@ -54,11 +56,6 @@ def add_outputs(self, outputs): raise ValueError(_msg.format("Input", o, self, type(o))) - - - - - class Bus(Node): pass From d7e3013151a3f910386172b705d1f401bb0befbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 28 Sep 2023 14:10:27 +0200 Subject: [PATCH 3/9] Adhere to Black --- tests/test_energy_system.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_energy_system.py b/tests/test_energy_system.py index 7d166b4..93ec9f8 100644 --- a/tests/test_energy_system.py +++ b/tests/test_energy_system.py @@ -58,7 +58,6 @@ def test_add_flow(self): node2.add_outputs({node1: Edge()}) assert (node2, node1) in self.es.flows().keys() - def test_that_node_additions_are_signalled(self): """ When a node gets `add`ed, a corresponding signal should be emitted. From c691376d97840ce020002e038f5043830debf0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Thu, 28 Sep 2023 14:23:40 +0200 Subject: [PATCH 4/9] Use ideomatic typecheck --- src/oemof/network/network/nodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oemof/network/network/nodes.py b/src/oemof/network/network/nodes.py index 79d51e9..262ff24 100644 --- a/src/oemof/network/network/nodes.py +++ b/src/oemof/network/network/nodes.py @@ -16,7 +16,7 @@ def _convert_to_dict(arg): - if type(arg) is dict: + if isinstance(arg, dict): return arg else: return dict.fromkeys(arg) From fdfac06d6c4f062556a058d399d5319dfc1af1b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 29 Sep 2023 09:54:15 +0200 Subject: [PATCH 5/9] Test that no flows are removed when adding new --- tests/test_energy_system.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_energy_system.py b/tests/test_energy_system.py index 93ec9f8..e0cfb33 100644 --- a/tests/test_energy_system.py +++ b/tests/test_energy_system.py @@ -45,17 +45,20 @@ def test_add_nodes(self): def test_add_flow(self): assert not self.es.nodes + node0 = Node(label="node0") node1 = Node(label="node1") - node2 = Node(label="node2") - - self.es.add(node1, node2) + node2 = Node(label="node2", inputs={node0: Edge()}) + self.es.add(node0, node1, node2) node2.add_inputs({node1: Edge()}) + assert (node0, node2) in self.es.flows().keys() assert (node1, node2) in self.es.flows().keys() assert (node2, node1) not in self.es.flows().keys() node2.add_outputs({node1: Edge()}) + assert (node0, node2) in self.es.flows().keys() + assert (node1, node2) in self.es.flows().keys() assert (node2, node1) in self.es.flows().keys() def test_that_node_additions_are_signalled(self): From b445e881a64ff3e76cdba7fb47201cd3fe75a46c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 6 Oct 2023 17:47:03 +0200 Subject: [PATCH 6/9] Revert changes in Node --- src/oemof/network/network/nodes.py | 39 ++++++++++++++---------------- tests/test_energy_system.py | 11 ++++++--- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/oemof/network/network/nodes.py b/src/oemof/network/network/nodes.py index c639487..7b11e6e 100644 --- a/src/oemof/network/network/nodes.py +++ b/src/oemof/network/network/nodes.py @@ -22,9 +22,6 @@ def _convert_to_dict(arg): return dict.fromkeys(arg) -_msg = "{} {!r} of {!r} not an instance of Node but of {}." - - class Node(Entity): r"""A Node of an energy system graph. @@ -44,29 +41,29 @@ def __init__(self, *args, **kwargs): self._in_edges = set() - inputs = kwargs.get("inputs", {}) - outputs = kwargs.get("outputs", {}) - self.add_inputs(inputs) - self.add_outputs(outputs) + msg = "{} {!r} of {!r} not an instance of Node but of {}." - def add_inputs(self, inputs): - input_dict = _convert_to_dict(inputs) - for i, e in input_dict.items(): + for i in kwargs.get("inputs", {}): if not isinstance(i, Node): - raise ValueError(_msg.format("Input", i, self, type(i))) + raise ValueError(msg.format("Input", i, self, type(i))) self._in_edges.add(i) - - edge = Edge.from_object(e) + try: + flow = kwargs["inputs"].get(i) + except AttributeError: + flow = None + edge = Edge.from_object(flow) edge.input = i edge.output = self - - def add_outputs(self, outputs): - output_dict = _convert_to_dict(outputs) - for o, f in output_dict.items(): - if isinstance(o, Node): - o.add_inputs({self: f}) - else: - raise ValueError(_msg.format("Input", o, self, type(o))) + for o in kwargs.get("outputs", {}): + if not isinstance(o, Node): + raise ValueError(msg.format("Output", o, self, type(o))) + try: + flow = kwargs["outputs"].get(o) + except AttributeError: + flow = None + edge = Edge.from_object(flow) + edge.input = self + edge.output = o class Bus(Node): diff --git a/tests/test_energy_system.py b/tests/test_energy_system.py index e0cfb33..6e602f5 100644 --- a/tests/test_energy_system.py +++ b/tests/test_energy_system.py @@ -42,7 +42,7 @@ def test_add_nodes(self): assert node2 in self.es.nodes assert (node1, node2) in self.es.flows().keys() - def test_add_flow(self): + def test_add_flow_assignment(self): assert not self.es.nodes node0 = Node(label="node0") @@ -50,13 +50,18 @@ def test_add_flow(self): node2 = Node(label="node2", inputs={node0: Edge()}) self.es.add(node0, node1, node2) - node2.add_inputs({node1: Edge()}) + + assert (node0, node2) in self.es.flows().keys() + assert (node1, node2) not in self.es.flows().keys() + assert (node2, node1) not in self.es.flows().keys() + + node2.inputs[node1] = Edge() assert (node0, node2) in self.es.flows().keys() assert (node1, node2) in self.es.flows().keys() assert (node2, node1) not in self.es.flows().keys() - node2.add_outputs({node1: Edge()}) + node2.outputs[node1] = Edge() assert (node0, node2) in self.es.flows().keys() assert (node1, node2) in self.es.flows().keys() assert (node2, node1) in self.es.flows().keys() From 95ce2a024cb01526f7c75733c82ea99de5b6a87c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Fri, 6 Oct 2023 17:48:25 +0200 Subject: [PATCH 7/9] Revert addition of now unused function --- src/oemof/network/network/nodes.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/oemof/network/network/nodes.py b/src/oemof/network/network/nodes.py index 7b11e6e..bc1e1e7 100644 --- a/src/oemof/network/network/nodes.py +++ b/src/oemof/network/network/nodes.py @@ -15,13 +15,6 @@ from .entity import Entity -def _convert_to_dict(arg): - if isinstance(arg, dict): - return arg - else: - return dict.fromkeys(arg) - - class Node(Entity): r"""A Node of an energy system graph. From 48105fd871f686a1fbed2653f466e9eb8d8c8e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Tue, 10 Oct 2023 10:53:46 +0200 Subject: [PATCH 8/9] Document attributes inputs/outputs of Node --- src/oemof/network/network/nodes.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/oemof/network/network/nodes.py b/src/oemof/network/network/nodes.py index bc1e1e7..8cbc983 100644 --- a/src/oemof/network/network/nodes.py +++ b/src/oemof/network/network/nodes.py @@ -24,9 +24,18 @@ class Node(Entity): inputs: list or dict, optional Either a list of this nodes' input nodes or a dictionary mapping input nodes to corresponding inflows (i.e. input values). + List will be converted to dictionary with values set to None. outputs: list or dict, optional Either a list of this nodes' output nodes or a dictionary mapping output nodes to corresponding outflows (i.e. output values). + List will be converted to dictionary with values set to None. + + Attributes + ---------- + inputs: dict + A dictionary mapping input nodes to corresponding inflows. + outputs: list or dict, optional + A dictionary mapping output nodes to corresponding outflows. """ def __init__(self, *args, **kwargs): From a50ad8474a6bbce894b29e34dfed26454b316477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Sch=C3=B6nfeldt?= Date: Tue, 10 Oct 2023 10:57:59 +0200 Subject: [PATCH 9/9] Fix inconsistency in docstring --- src/oemof/network/network/nodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oemof/network/network/nodes.py b/src/oemof/network/network/nodes.py index 8cbc983..0a4b6c9 100644 --- a/src/oemof/network/network/nodes.py +++ b/src/oemof/network/network/nodes.py @@ -34,7 +34,7 @@ class Node(Entity): ---------- inputs: dict A dictionary mapping input nodes to corresponding inflows. - outputs: list or dict, optional + outputs: dict A dictionary mapping output nodes to corresponding outflows. """